Add support for savepoints to fts5.

FossilOrigin-Name: 3b19eba042bb2eeb1be60f8d58ebaa0a045d6a5c
This commit is contained in:
dan 2014-08-06 16:30:21 +00:00
parent 192d413e95
commit 7b71fbaf93
8 changed files with 281 additions and 73 deletions

View File

@ -13,14 +13,52 @@
** This is an SQLite module implementing full-text search. ** This is an SQLite module implementing full-text search.
*/ */
#include "fts5Int.h" #include "fts5Int.h"
typedef struct Fts5Table Fts5Table; typedef struct Fts5Table Fts5Table;
typedef struct Fts5Cursor Fts5Cursor; typedef struct Fts5Cursor Fts5Cursor;
typedef struct Fts5Global Fts5Global; typedef struct Fts5Global Fts5Global;
typedef struct Fts5Auxiliary Fts5Auxiliary; typedef struct Fts5Auxiliary Fts5Auxiliary;
typedef struct Fts5Auxdata Fts5Auxdata; typedef struct Fts5Auxdata Fts5Auxdata;
/*
** NOTES ON TRANSACTIONS:
**
** SQLite invokes the following virtual table methods as transactions are
** opened and closed by the user:
**
** xBegin(): Start of a new transaction.
** xSync(): Initial part of two-phase commit.
** xCommit(): Final part of two-phase commit.
** xRollback(): Rollback the transaction.
**
** Anything that is required as part of a commit that may fail is performed
** in the xSync() callback. Current versions of SQLite ignore any errors
** returned by xCommit().
**
** And as sub-transactions are opened/closed:
**
** xSavepoint(int S): Open savepoint S.
** xRelease(int S): Commit and close savepoint S.
** xRollbackTo(int S): Rollback to start of savepoint S.
**
** During a write-transaction the fts5_index.c module may cache some data
** in-memory. It is flushed to disk whenever xSync(), xRelease() or
** xSavepoint() is called. And discarded whenever xRollback() or xRollbackTo()
** is called.
**
** Additionally, if SQLITE_DEBUG is defined, an instance of the following
** structure is used to record the current transaction state. This information
** is not required, but it is used in the assert() statements executed by
** function fts5CheckTransactionState() (see below).
*/
struct Fts5TransactionState {
int eState; /* 0==closed, 1==open, 2==synced */
int iSavepoint; /* Number of open savepoints (0 -> none) */
};
/* /*
** A single object of this type is allocated when the FTS5 module is ** A single object of this type is allocated when the FTS5 module is
** registered with a database handle. It is used to store pointers to ** registered with a database handle. It is used to store pointers to
@ -57,6 +95,9 @@ struct Fts5Table {
Fts5Storage *pStorage; /* Document store */ Fts5Storage *pStorage; /* Document store */
Fts5Global *pGlobal; /* Global (connection wide) data */ Fts5Global *pGlobal; /* Global (connection wide) data */
Fts5Cursor *pSortCsr; /* Sort data from this cursor */ Fts5Cursor *pSortCsr; /* Sort data from this cursor */
#ifdef SQLITE_DEBUG
struct Fts5TransactionState ts;
#endif
}; };
struct Fts5MatchPhrase { struct Fts5MatchPhrase {
@ -130,6 +171,64 @@ struct Fts5Auxdata {
Fts5Auxdata *pNext; /* Next object in linked list */ Fts5Auxdata *pNext; /* Next object in linked list */
}; };
#ifdef SQLITE_DEBUG
#define FTS5_BEGIN 1
#define FTS5_SYNC 2
#define FTS5_COMMIT 3
#define FTS5_ROLLBACK 4
#define FTS5_SAVEPOINT 5
#define FTS5_RELEASE 6
#define FTS5_ROLLBACKTO 7
static void fts5CheckTransactionState(Fts5Table *p, int op, int iSavepoint){
switch( op ){
case FTS5_BEGIN:
assert( p->ts.eState==0 );
p->ts.eState = 1;
p->ts.iSavepoint = -1;
break;
case FTS5_SYNC:
assert( p->ts.eState==1 );
p->ts.eState = 2;
break;
case FTS5_COMMIT:
assert( p->ts.eState==2 );
p->ts.eState = 0;
break;
case FTS5_ROLLBACK:
assert( p->ts.eState==1 || p->ts.eState==2 );
p->ts.eState = 0;
break;
case FTS5_SAVEPOINT:
assert( p->ts.eState==1 );
assert( iSavepoint>=0 );
assert( iSavepoint>p->ts.iSavepoint );
p->ts.iSavepoint = iSavepoint;
break;
case FTS5_RELEASE:
assert( p->ts.eState==1 );
assert( iSavepoint>=0 );
assert( iSavepoint<=p->ts.iSavepoint );
p->ts.iSavepoint = iSavepoint-1;
break;
case FTS5_ROLLBACKTO:
assert( p->ts.eState==1 );
assert( iSavepoint>=0 );
assert( iSavepoint<=p->ts.iSavepoint );
p->ts.iSavepoint = iSavepoint;
break;
}
}
#else
# define fts5CheckTransactionState(x,y,z)
#endif
/* /*
** Close a virtual table handle opened by fts5InitVtab(). If the bDestroy ** Close a virtual table handle opened by fts5InitVtab(). If the bDestroy
** argument is non-zero, attempt delete the shadow tables from teh database ** argument is non-zero, attempt delete the shadow tables from teh database
@ -222,6 +321,8 @@ static int fts5InitVtab(
if( rc!=SQLITE_OK ){ if( rc!=SQLITE_OK ){
fts5FreeVtab(pTab, 0); fts5FreeVtab(pTab, 0);
pTab = 0; pTab = 0;
}else if( bCreate ){
fts5CheckTransactionState(pTab, FTS5_BEGIN, 0);
} }
*ppVTab = (sqlite3_vtab*)pTab; *ppVTab = (sqlite3_vtab*)pTab;
return rc; return rc;
@ -793,6 +894,9 @@ static int fts5UpdateMethod(
int eConflict; /* ON CONFLICT for this DML */ int eConflict; /* ON CONFLICT for this DML */
int rc = SQLITE_OK; /* Return code */ int rc = SQLITE_OK; /* Return code */
/* A transaction must be open when this is called. */
assert( pTab->ts.eState==1 );
/* A delete specifies a single argument - the rowid of the row to remove. /* A delete specifies a single argument - the rowid of the row to remove.
** Update and insert operations pass: ** Update and insert operations pass:
** **
@ -829,7 +933,8 @@ static int fts5UpdateMethod(
static int fts5SyncMethod(sqlite3_vtab *pVtab){ static int fts5SyncMethod(sqlite3_vtab *pVtab){
int rc; int rc;
Fts5Table *pTab = (Fts5Table*)pVtab; Fts5Table *pTab = (Fts5Table*)pVtab;
rc = sqlite3Fts5IndexSync(pTab->pIndex); fts5CheckTransactionState(pTab, FTS5_SYNC, 0);
rc = sqlite3Fts5IndexSync(pTab->pIndex, 1);
return rc; return rc;
} }
@ -837,6 +942,7 @@ static int fts5SyncMethod(sqlite3_vtab *pVtab){
** Implementation of xBegin() method. ** Implementation of xBegin() method.
*/ */
static int fts5BeginMethod(sqlite3_vtab *pVtab){ static int fts5BeginMethod(sqlite3_vtab *pVtab){
fts5CheckTransactionState((Fts5Table*)pVtab, FTS5_BEGIN, 0);
return SQLITE_OK; return SQLITE_OK;
} }
@ -846,6 +952,7 @@ static int fts5BeginMethod(sqlite3_vtab *pVtab){
** by fts5SyncMethod(). ** by fts5SyncMethod().
*/ */
static int fts5CommitMethod(sqlite3_vtab *pVtab){ static int fts5CommitMethod(sqlite3_vtab *pVtab){
fts5CheckTransactionState((Fts5Table*)pVtab, FTS5_COMMIT, 0);
return SQLITE_OK; return SQLITE_OK;
} }
@ -854,8 +961,9 @@ static int fts5CommitMethod(sqlite3_vtab *pVtab){
** hash-table. Any changes made to the database are reverted by SQLite. ** hash-table. Any changes made to the database are reverted by SQLite.
*/ */
static int fts5RollbackMethod(sqlite3_vtab *pVtab){ static int fts5RollbackMethod(sqlite3_vtab *pVtab){
Fts5Table *pTab = (Fts5Table*)pVtab;
int rc; int rc;
Fts5Table *pTab = (Fts5Table*)pVtab;
fts5CheckTransactionState(pTab, FTS5_ROLLBACK, 0);
rc = sqlite3Fts5IndexRollback(pTab->pIndex); rc = sqlite3Fts5IndexRollback(pTab->pIndex);
return rc; return rc;
} }
@ -1243,8 +1351,9 @@ static int fts5RenameMethod(
** Flush the contents of the pending-terms table to disk. ** Flush the contents of the pending-terms table to disk.
*/ */
static int fts5SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){ static int fts5SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
int rc = SQLITE_OK; Fts5Table *pTab = (Fts5Table*)pVtab;
return rc; fts5CheckTransactionState(pTab, FTS5_SAVEPOINT, iSavepoint);
return sqlite3Fts5IndexSync(pTab->pIndex, 0);
} }
/* /*
@ -1253,7 +1362,9 @@ static int fts5SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
** This is a no-op. ** This is a no-op.
*/ */
static int fts5ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){ static int fts5ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){
return SQLITE_OK; Fts5Table *pTab = (Fts5Table*)pVtab;
fts5CheckTransactionState(pTab, FTS5_RELEASE, iSavepoint);
return sqlite3Fts5IndexSync(pTab->pIndex, 0);
} }
/* /*
@ -1262,7 +1373,9 @@ static int fts5ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){
** Discard the contents of the pending terms table. ** Discard the contents of the pending terms table.
*/ */
static int fts5RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){ static int fts5RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){
return SQLITE_OK; Fts5Table *pTab = (Fts5Table*)pVtab;
fts5CheckTransactionState(pTab, FTS5_ROLLBACKTO, iSavepoint);
return sqlite3Fts5IndexRollback(pTab->pIndex);
} }
/* /*

View File

@ -72,6 +72,7 @@ void sqlite3Fts5Dequote(char *z);
**************************************************************************/ **************************************************************************/
/************************************************************************** /**************************************************************************
** Interface to code in fts5_buffer.c.
*/ */
/* /*
@ -156,7 +157,6 @@ typedef struct Fts5IndexIter Fts5IndexIter;
*/ */
#define FTS5INDEX_QUERY_PREFIX 0x0001 /* Prefix query */ #define FTS5INDEX_QUERY_PREFIX 0x0001 /* Prefix query */
#define FTS5INDEX_QUERY_ASC 0x0002 /* Docs in ascending rowid order */ #define FTS5INDEX_QUERY_ASC 0x0002 /* Docs in ascending rowid order */
#define FTS5INDEX_QUERY_MATCH 0x0004 /* Use the iMatch arg to Next() */
/* /*
** Create/destroy an Fts5Index object. ** Create/destroy an Fts5Index object.
@ -230,22 +230,15 @@ void sqlite3Fts5IndexBeginWrite(
/* /*
** Flush any data stored in the in-memory hash tables to the database. ** Flush any data stored in the in-memory hash tables to the database.
** ** If the bCommit flag is true, also close any open blob handles.
** This is called whenever (a) the main transaction is committed or (b) a
** new sub-transaction is opened.
*/ */
void sqlite3Fts5IndexFlush(Fts5Index *p); int sqlite3Fts5IndexSync(Fts5Index *p, int bCommit);
int sqlite3Fts5IndexSync(Fts5Index *p);
/* /*
** Discard any data stored in the in-memory hash tables. Do not write it ** Discard any data stored in the in-memory hash tables. Do not write it
** to the database. Additionally, assume that the contents of the %_data ** to the database. Additionally, assume that the contents of the %_data
** table may have changed on disk. So any in-memory caches of %_data ** table may have changed on disk. So any in-memory caches of %_data
** records must be invalidated. ** records must be invalidated.
**
** This is called (a) whenever a main or sub-transaction is rolled back,
** and (b) whenever the read transaction is closed.
*/ */
int sqlite3Fts5IndexRollback(Fts5Index *p); int sqlite3Fts5IndexRollback(Fts5Index *p);
@ -256,9 +249,10 @@ int sqlite3Fts5IndexErrcode(Fts5Index*);
void sqlite3Fts5IndexReset(Fts5Index*); void sqlite3Fts5IndexReset(Fts5Index*);
/* /*
** Get (bSet==0) or set (bSet!=0) the "averages" record. ** Get or set the "averages" record.
*/ */
void sqlite3Fts5IndexAverages(Fts5Index *p, int bSet, int nAvg, int *aAvg); int sqlite3Fts5IndexGetAverages(Fts5Index *p, Fts5Buffer *pBuf);
int sqlite3Fts5IndexSetAverages(Fts5Index *p, const u8*, int);
/* /*
** Functions called by the storage module as part of integrity-check. ** Functions called by the storage module as part of integrity-check.
@ -266,14 +260,23 @@ void sqlite3Fts5IndexAverages(Fts5Index *p, int bSet, int nAvg, int *aAvg);
u64 sqlite3Fts5IndexCksum(Fts5Config*,i64,int,int,const char*,int); u64 sqlite3Fts5IndexCksum(Fts5Config*,i64,int,int,const char*,int);
int sqlite3Fts5IndexIntegrityCheck(Fts5Index*, u64 cksum); int sqlite3Fts5IndexIntegrityCheck(Fts5Index*, u64 cksum);
/* Called during startup to register a UDF with SQLite */ /*
** Called during virtual module initialization to register UDF
** fts5_decode() with SQLite
*/
int sqlite3Fts5IndexInit(sqlite3*); int sqlite3Fts5IndexInit(sqlite3*);
/*
** Set the page size to use when writing. It doesn't matter if this
** changes mid-transaction, or if inconsistent values are used by
** multiple clients.
*/
void sqlite3Fts5IndexPgsz(Fts5Index *p, int pgsz); void sqlite3Fts5IndexPgsz(Fts5Index *p, int pgsz);
int sqlite3Fts5IndexGetAverages(Fts5Index *p, Fts5Buffer *pBuf); /*
int sqlite3Fts5IndexSetAverages(Fts5Index *p, const u8*, int); ** Return the total number of entries read from the %_data table by
** this connection since it was created.
*/
int sqlite3Fts5IndexReads(Fts5Index *p); int sqlite3Fts5IndexReads(Fts5Index *p);
/* /*

View File

@ -745,9 +745,10 @@ static void fts5TestFunction(
memset(&s, 0, sizeof(Fts5Buffer)); memset(&s, 0, sizeof(Fts5Buffer));
nCol = pApi->xColumnCount(pFts); nCol = pApi->xColumnCount(pFts);
if( zReq==0 ){ /*
sqlite3Fts5BufferAppendPrintf(&rc, &s, "columntotalsize "); ** xColumnTotalSize()
} */
if( zReq==0 ) sqlite3Fts5BufferAppendPrintf(&rc, &s, "columntotalsize ");
if( 0==zReq || 0==sqlite3_stricmp(zReq, "columntotalsize") ){ if( 0==zReq || 0==sqlite3_stricmp(zReq, "columntotalsize") ){
if( zReq==0 && nCol>1 ) sqlite3Fts5BufferAppendPrintf(&rc, &s, "{"); if( zReq==0 && nCol>1 ) sqlite3Fts5BufferAppendPrintf(&rc, &s, "{");
for(i=0; rc==SQLITE_OK && i<nCol; i++){ for(i=0; rc==SQLITE_OK && i<nCol; i++){
@ -758,16 +759,19 @@ static void fts5TestFunction(
if( zReq==0 && nCol>1 ) sqlite3Fts5BufferAppendPrintf(&rc, &s, "}"); if( zReq==0 && nCol>1 ) sqlite3Fts5BufferAppendPrintf(&rc, &s, "}");
} }
if( zReq==0 ){ /*
sqlite3Fts5BufferAppendPrintf(&rc, &s, " columncount "); ** xColumnCount()
} */
if( zReq==0 ) sqlite3Fts5BufferAppendPrintf(&rc, &s, " columncount ");
if( 0==zReq || 0==sqlite3_stricmp(zReq, "columncount") ){ if( 0==zReq || 0==sqlite3_stricmp(zReq, "columncount") ){
nCol = pApi->xColumnCount(pFts);
sqlite3Fts5BufferAppendPrintf(&rc, &s, "%d", nCol); sqlite3Fts5BufferAppendPrintf(&rc, &s, "%d", nCol);
} }
if( zReq==0 ){ /*
sqlite3Fts5BufferAppendPrintf(&rc, &s, " columnsize "); ** xColumnSize()
} */
if( zReq==0 ) sqlite3Fts5BufferAppendPrintf(&rc, &s, " columnsize ");
if( 0==zReq || 0==sqlite3_stricmp(zReq, "columnsize") ){ if( 0==zReq || 0==sqlite3_stricmp(zReq, "columnsize") ){
if( zReq==0 && nCol>1 ) sqlite3Fts5BufferAppendPrintf(&rc, &s, "{"); if( zReq==0 && nCol>1 ) sqlite3Fts5BufferAppendPrintf(&rc, &s, "{");
for(i=0; rc==SQLITE_OK && i<nCol; i++){ for(i=0; rc==SQLITE_OK && i<nCol; i++){
@ -778,9 +782,10 @@ static void fts5TestFunction(
if( zReq==0 && nCol>1 ) sqlite3Fts5BufferAppendPrintf(&rc, &s, "}"); if( zReq==0 && nCol>1 ) sqlite3Fts5BufferAppendPrintf(&rc, &s, "}");
} }
if( zReq==0 ){ /*
sqlite3Fts5BufferAppendPrintf(&rc, &s, " columntext "); ** xColumnText()
} */
if( zReq==0 ) sqlite3Fts5BufferAppendPrintf(&rc, &s, " columntext ");
if( 0==zReq || 0==sqlite3_stricmp(zReq, "columntext") ){ if( 0==zReq || 0==sqlite3_stricmp(zReq, "columntext") ){
for(i=0; rc==SQLITE_OK && i<nCol; i++){ for(i=0; rc==SQLITE_OK && i<nCol; i++){
const char *z; const char *z;
@ -791,17 +796,19 @@ static void fts5TestFunction(
} }
} }
if( zReq==0 ){ /*
sqlite3Fts5BufferAppendPrintf(&rc, &s, " phrasecount "); ** xPhraseCount()
} */
if( zReq==0 ) sqlite3Fts5BufferAppendPrintf(&rc, &s, " phrasecount ");
nPhrase = pApi->xPhraseCount(pFts); nPhrase = pApi->xPhraseCount(pFts);
if( 0==zReq || 0==sqlite3_stricmp(zReq, "phrasecount") ){ if( 0==zReq || 0==sqlite3_stricmp(zReq, "phrasecount") ){
sqlite3Fts5BufferAppendPrintf(&rc, &s, "%d", nPhrase); sqlite3Fts5BufferAppendPrintf(&rc, &s, "%d", nPhrase);
} }
if( zReq==0 ){ /*
sqlite3Fts5BufferAppendPrintf(&rc, &s, " phrasesize "); ** xPhraseSize()
} */
if( zReq==0 ) sqlite3Fts5BufferAppendPrintf(&rc, &s, " phrasesize ");
if( 0==zReq || 0==sqlite3_stricmp(zReq, "phrasesize") ){ if( 0==zReq || 0==sqlite3_stricmp(zReq, "phrasesize") ){
if( nPhrase==1 ){ if( nPhrase==1 ){
int nSize = pApi->xPhraseSize(pFts, 0); int nSize = pApi->xPhraseSize(pFts, 0);
@ -816,15 +823,15 @@ static void fts5TestFunction(
} }
} }
if( zReq==0 ){ /*
sqlite3Fts5BufferAppendPrintf(&rc, &s, " poslist "); ** xPoslist()
} */
if( zReq==0 ) sqlite3Fts5BufferAppendPrintf(&rc, &s, " poslist ");
if( 0==zReq || 0==sqlite3_stricmp(zReq, "poslist") ){ if( 0==zReq || 0==sqlite3_stricmp(zReq, "poslist") ){
int bParen = 0; int bParen = 0;
Fts5Buffer s3; Fts5Buffer s3;
memset(&s3, 0, sizeof(s3)); memset(&s3, 0, sizeof(s3));
for(i=0; i<nPhrase; i++){ for(i=0; i<nPhrase; i++){
Fts5Buffer s2; /* List of positions for phrase/column */ Fts5Buffer s2; /* List of positions for phrase/column */
int j = 0; int j = 0;

View File

@ -754,6 +754,16 @@ fprintf(stdout, "read: %s\n", buf.p);
fflush(stdout); fflush(stdout);
sqlite3_free(buf.p); sqlite3_free(buf.p);
#endif #endif
if( p->pReader ){
/* This call may return SQLITE_ABORT if there has been a savepoint
** rollback since it was last used. In this case a new blob handle
** is required. */
rc = sqlite3_blob_reopen(p->pReader, iRowid);
if( rc==SQLITE_ABORT ){
fts5CloseReader(p);
rc = SQLITE_OK;
}
}
/* If the blob handle is not yet open, open and seek it. Otherwise, use /* If the blob handle is not yet open, open and seek it. Otherwise, use
** the blob_reopen() API to reseek the existing blob handle. */ ** the blob_reopen() API to reseek the existing blob handle. */
@ -762,8 +772,6 @@ sqlite3_free(buf.p);
rc = sqlite3_blob_open(pConfig->db, rc = sqlite3_blob_open(pConfig->db,
pConfig->zDb, p->zDataTbl, "block", iRowid, 0, &p->pReader pConfig->zDb, p->zDataTbl, "block", iRowid, 0, &p->pReader
); );
}else{
rc = sqlite3_blob_reopen(p->pReader, iRowid);
} }
if( rc ) fts5MissingData(); if( rc ) fts5MissingData();
@ -2482,6 +2490,25 @@ static Fts5PendingDoclist *fts5PendingList(Fts5Index *p, int iHash){
return pList; return pList;
} }
/*
** Discard all data currently cached in the hash-tables.
*/
static void fts5IndexDiscardData(Fts5Index *p){
Fts5Config *pConfig = p->pConfig;
int i;
for(i=0; i<=pConfig->nPrefix; i++){
Fts3Hash *pHash = &p->aHash[i];
Fts3HashElem *pE; /* Iterator variable */
for(pE=fts3HashFirst(pHash); pE; pE=fts3HashNext(pE)){
Fts5PendingDoclist *pDoclist = (Fts5PendingDoclist*)fts3HashData(pE);
fts5FreePendingDoclist(pDoclist);
}
fts3HashClear(pHash);
}
p->nPendingData = 0;
}
/* /*
** Return the size of the prefix, in bytes, that buffer (nNew/pNew) shares ** Return the size of the prefix, in bytes, that buffer (nNew/pNew) shares
** with buffer (nOld/pOld). ** with buffer (nOld/pOld).
@ -3145,21 +3172,10 @@ static void fts5FlushOneHash(Fts5Index *p, int iHash, int *pnLeaf){
fts5StructureRelease(pStruct); fts5StructureRelease(pStruct);
} }
/*
** Indicate that all subsequent calls to sqlite3Fts5IndexWrite() pertain
** to the document with rowid iRowid.
*/
void sqlite3Fts5IndexBeginWrite(Fts5Index *p, i64 iRowid){
if( iRowid<=p->iWriteRowid ){
sqlite3Fts5IndexFlush(p);
}
p->iWriteRowid = iRowid;
}
/* /*
** Flush any data stored in the in-memory hash tables to the database. ** Flush any data stored in the in-memory hash tables to the database.
*/ */
void sqlite3Fts5IndexFlush(Fts5Index *p){ static void fts5IndexFlush(Fts5Index *p){
Fts5Config *pConfig = p->pConfig; Fts5Config *pConfig = p->pConfig;
int i; /* Used to iterate through indexes */ int i; /* Used to iterate through indexes */
int nLeaf = 0; /* Number of leaves written */ int nLeaf = 0; /* Number of leaves written */
@ -3175,12 +3191,23 @@ void sqlite3Fts5IndexFlush(Fts5Index *p){
p->nPendingData = 0; p->nPendingData = 0;
} }
/*
** Indicate that all subsequent calls to sqlite3Fts5IndexWrite() pertain
** to the document with rowid iRowid.
*/
void sqlite3Fts5IndexBeginWrite(Fts5Index *p, i64 iRowid){
if( iRowid<=p->iWriteRowid ){
fts5IndexFlush(p);
}
p->iWriteRowid = iRowid;
}
/* /*
** Commit data to disk. ** Commit data to disk.
*/ */
int sqlite3Fts5IndexSync(Fts5Index *p){ int sqlite3Fts5IndexSync(Fts5Index *p, int bCommit){
sqlite3Fts5IndexFlush(p); fts5IndexFlush(p);
fts5CloseReader(p); if( bCommit ) fts5CloseReader(p);
return p->rc; return p->rc;
} }
@ -3192,6 +3219,7 @@ int sqlite3Fts5IndexSync(Fts5Index *p){
*/ */
int sqlite3Fts5IndexRollback(Fts5Index *p){ int sqlite3Fts5IndexRollback(Fts5Index *p){
fts5CloseReader(p); fts5CloseReader(p);
fts5IndexDiscardData(p);
return SQLITE_OK; return SQLITE_OK;
} }

View File

@ -1,5 +1,5 @@
C Use\sdoclist\sindexes\sfor\sAND\squeries\sas\swell\sas\sphrases. C Add\ssupport\sfor\ssavepoints\sto\sfts5.
D 2014-08-05T19:35:20.490 D 2014-08-06T16:30:21.057
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in b03432313a3aad96c706f8164fb9f5307eaf19f5 F Makefile.in b03432313a3aad96c706f8164fb9f5307eaf19f5
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@ -103,14 +103,14 @@ F ext/fts3/tool/fts3view.c 6cfc5b67a5f0e09c0d698f9fd012c784bfaa9197
F ext/fts3/unicode/CaseFolding.txt 8c678ca52ecc95e16bc7afc2dbf6fc9ffa05db8c F ext/fts3/unicode/CaseFolding.txt 8c678ca52ecc95e16bc7afc2dbf6fc9ffa05db8c
F ext/fts3/unicode/UnicodeData.txt cd07314edb62d49fde34debdaf92fa2aa69011e7 F ext/fts3/unicode/UnicodeData.txt cd07314edb62d49fde34debdaf92fa2aa69011e7
F ext/fts3/unicode/mkunicode.tcl dc6f268eb526710e2c6e496c372471d773d0c368 F ext/fts3/unicode/mkunicode.tcl dc6f268eb526710e2c6e496c372471d773d0c368
F ext/fts5/fts5.c 23f875e24ffa722107690d14b449141a25a2d697 F ext/fts5/fts5.c 15e585ed0194f94a1da360808f29184f9d44554c
F ext/fts5/fts5.h 8ace10d5b249a3baa983c79e7a1306d2a79cfd6a F ext/fts5/fts5.h 8ace10d5b249a3baa983c79e7a1306d2a79cfd6a
F ext/fts5/fts5Int.h aef50f3078e60707aeb2e4b2787d8c5eecdd02dc F ext/fts5/fts5Int.h 410001da21bcc3d09b4290d4858352d0985ac7a6
F ext/fts5/fts5_aux.c 366057c7186bc3615deb5ecc0ff61de50b6d2dbc F ext/fts5/fts5_aux.c 31e581413ecab0962ce2b37468f9f658f36f4b0e
F ext/fts5/fts5_buffer.c 248c61ac9fec001602efc72a45704f3b8d367c00 F ext/fts5/fts5_buffer.c 248c61ac9fec001602efc72a45704f3b8d367c00
F ext/fts5/fts5_config.c f4ebf143e141b8c77355e3b15aba81b7be51d710 F ext/fts5/fts5_config.c f4ebf143e141b8c77355e3b15aba81b7be51d710
F ext/fts5/fts5_expr.c 7b8e380233176053841904a86006696ee8f6cd24 F ext/fts5/fts5_expr.c 7b8e380233176053841904a86006696ee8f6cd24
F ext/fts5/fts5_index.c 40d9086948d6f1420a078bd9fb0b5372e54ec791 F ext/fts5/fts5_index.c 6a9f851490562d8843edc4d54b27eb9472c62d68
F ext/fts5/fts5_storage.c 2866e7e1de9dc851756c3a9c76b6e1d75e0facb7 F ext/fts5/fts5_storage.c 2866e7e1de9dc851756c3a9c76b6e1d75e0facb7
F ext/fts5/fts5parse.y 777da8e5819f75c217982c79c29d014c293acac9 F ext/fts5/fts5parse.y 777da8e5819f75c217982c79c29d014c293acac9
F ext/icu/README.txt d9fbbad0c2f647c3fdf715fc9fd64af53aedfc43 F ext/icu/README.txt d9fbbad0c2f647c3fdf715fc9fd64af53aedfc43
@ -603,6 +603,7 @@ F test/fts5ae.test cb37b3135a00d3afd5492ec534ecf654be5ff69e
F test/fts5af.test 9ebe23aa3875896076952c7bc6e8308813a63c74 F test/fts5af.test 9ebe23aa3875896076952c7bc6e8308813a63c74
F test/fts5ag.test 0747bf3bade16d5165810cf891f875933b28b420 F test/fts5ag.test 0747bf3bade16d5165810cf891f875933b28b420
F test/fts5ah.test 009b993a9b7ebc43f84c10e53bd778b1dc8ffbe7 F test/fts5ah.test 009b993a9b7ebc43f84c10e53bd778b1dc8ffbe7
F test/fts5ai.test 4dee71c23ddbcf2b0fc5d5586f241002b883c10e
F test/fts5ea.test ff43b40f8879ba50b82def70f2ab67c195d1a1d4 F test/fts5ea.test ff43b40f8879ba50b82def70f2ab67c195d1a1d4
F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d
F test/func.test ae97561957aba6ca9e3a7b8a13aac41830d701ef F test/func.test ae97561957aba6ca9e3a7b8a13aac41830d701ef
@ -770,7 +771,7 @@ F test/pagesize.test 1dd51367e752e742f58e861e65ed7390603827a0
F test/pcache.test b09104b03160aca0d968d99e8cd2c5b1921a993d F test/pcache.test b09104b03160aca0d968d99e8cd2c5b1921a993d
F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025 F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025
F test/percentile.test b98fc868d71eb5619d42a1702e9ab91718cbed54 F test/percentile.test b98fc868d71eb5619d42a1702e9ab91718cbed54
F test/permutations.test 542edb965245565d06b9284e708f17bb93d70691 F test/permutations.test 9875e7bacd0ab0cf78525e4b2d287840f284599b
F test/pragma.test adb21a90875bc54a880fa939c4d7c46598905aa0 F test/pragma.test adb21a90875bc54a880fa939c4d7c46598905aa0
F test/pragma2.test aea7b3d82c76034a2df2b38a13745172ddc0bc13 F test/pragma2.test aea7b3d82c76034a2df2b38a13745172ddc0bc13
F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552 F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552
@ -1199,7 +1200,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
P d028ba6589f3122b635474c2683c0f93d5bc6c7c P 5d38e6edc40ef188fbf96505073797036aa6783a
R df749c2987e3f7fa39a4c1c54f5a22e6 R e4475b88a5ed55985c58ff03d579a6b6
U dan U dan
Z 78f1e7641fc2b68987e4a3c99853c1c0 Z 1737719499cd3c712a0cb60804b1642b

View File

@ -1 +1 @@
5d38e6edc40ef188fbf96505073797036aa6783a 3b19eba042bb2eeb1be60f8d58ebaa0a045d6a5c

56
test/fts5ai.test Normal file
View File

@ -0,0 +1,56 @@
# 2014 June 17
#
# 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 implements regression tests for SQLite library. The
# focus of this script is testing the FTS5 module.
#
# Specifically, it tests transactions and savepoints
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix fts5ai
# If SQLITE_ENABLE_FTS3 is defined, omit this file.
ifcapable !fts3 {
finish_test
return
}
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE t1 USING fts5(a);
} {}
do_execsql_test 1.1 {
BEGIN;
INSERT INTO t1 VALUES('a b c');
INSERT INTO t1 VALUES('d e f');
SAVEPOINT one;
INSERT INTO t1 VALUES('g h i');
SAVEPOINT two;
INSERT INTO t1 VALUES('j k l');
ROLLBACK TO one;
INSERT INTO t1 VALUES('m n o');
SAVEPOINT two;
INSERT INTO t1 VALUES('p q r');
RELEASE one;
SAVEPOINT one;
INSERT INTO t1 VALUES('s t u');
ROLLBACK TO one;
COMMIT;
}
do_execsql_test 1.2 {
INSERT INTO t1(t1) VALUES('integrity-check');
}
finish_test

View File

@ -226,7 +226,7 @@ test_suite "fts5" -prefix "" -description {
All FTS5 tests. All FTS5 tests.
} -files { } -files {
fts5aa.test fts5ab.test fts5ac.test fts5ad.test fts5ae.test fts5ea.test fts5aa.test fts5ab.test fts5ac.test fts5ad.test fts5ae.test fts5ea.test
fts5af.test fts5ag.test fts5ah.test fts5af.test fts5ag.test fts5ah.test fts5ai.test
} }
test_suite "nofaultsim" -prefix "" -description { test_suite "nofaultsim" -prefix "" -description {