From 7b71fbaf93ca401372e7fced0296460a9d8b6197 Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 6 Aug 2014 16:30:21 +0000 Subject: [PATCH] Add support for savepoints to fts5. FossilOrigin-Name: 3b19eba042bb2eeb1be60f8d58ebaa0a045d6a5c --- ext/fts5/fts5.c | 125 +++++++++++++++++++++++++++++++++++++++-- ext/fts5/fts5Int.h | 35 ++++++------ ext/fts5/fts5_aux.c | 51 +++++++++-------- ext/fts5/fts5_index.c | 62 ++++++++++++++------ manifest | 21 +++---- manifest.uuid | 2 +- test/fts5ai.test | 56 ++++++++++++++++++ test/permutations.test | 2 +- 8 files changed, 281 insertions(+), 73 deletions(-) create mode 100644 test/fts5ai.test diff --git a/ext/fts5/fts5.c b/ext/fts5/fts5.c index d2a5f0ce6e..06d5b8c70b 100644 --- a/ext/fts5/fts5.c +++ b/ext/fts5/fts5.c @@ -13,14 +13,52 @@ ** This is an SQLite module implementing full-text search. */ + #include "fts5Int.h" + typedef struct Fts5Table Fts5Table; typedef struct Fts5Cursor Fts5Cursor; typedef struct Fts5Global Fts5Global; typedef struct Fts5Auxiliary Fts5Auxiliary; 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 ** registered with a database handle. It is used to store pointers to @@ -57,6 +95,9 @@ struct Fts5Table { Fts5Storage *pStorage; /* Document store */ Fts5Global *pGlobal; /* Global (connection wide) data */ Fts5Cursor *pSortCsr; /* Sort data from this cursor */ +#ifdef SQLITE_DEBUG + struct Fts5TransactionState ts; +#endif }; struct Fts5MatchPhrase { @@ -130,6 +171,64 @@ struct Fts5Auxdata { 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 ** argument is non-zero, attempt delete the shadow tables from teh database @@ -222,6 +321,8 @@ static int fts5InitVtab( if( rc!=SQLITE_OK ){ fts5FreeVtab(pTab, 0); pTab = 0; + }else if( bCreate ){ + fts5CheckTransactionState(pTab, FTS5_BEGIN, 0); } *ppVTab = (sqlite3_vtab*)pTab; return rc; @@ -793,6 +894,9 @@ static int fts5UpdateMethod( int eConflict; /* ON CONFLICT for this DML */ 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. ** Update and insert operations pass: ** @@ -829,7 +933,8 @@ static int fts5UpdateMethod( static int fts5SyncMethod(sqlite3_vtab *pVtab){ int rc; Fts5Table *pTab = (Fts5Table*)pVtab; - rc = sqlite3Fts5IndexSync(pTab->pIndex); + fts5CheckTransactionState(pTab, FTS5_SYNC, 0); + rc = sqlite3Fts5IndexSync(pTab->pIndex, 1); return rc; } @@ -837,6 +942,7 @@ static int fts5SyncMethod(sqlite3_vtab *pVtab){ ** Implementation of xBegin() method. */ static int fts5BeginMethod(sqlite3_vtab *pVtab){ + fts5CheckTransactionState((Fts5Table*)pVtab, FTS5_BEGIN, 0); return SQLITE_OK; } @@ -846,6 +952,7 @@ static int fts5BeginMethod(sqlite3_vtab *pVtab){ ** by fts5SyncMethod(). */ static int fts5CommitMethod(sqlite3_vtab *pVtab){ + fts5CheckTransactionState((Fts5Table*)pVtab, FTS5_COMMIT, 0); 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. */ static int fts5RollbackMethod(sqlite3_vtab *pVtab){ - Fts5Table *pTab = (Fts5Table*)pVtab; int rc; + Fts5Table *pTab = (Fts5Table*)pVtab; + fts5CheckTransactionState(pTab, FTS5_ROLLBACK, 0); rc = sqlite3Fts5IndexRollback(pTab->pIndex); return rc; } @@ -1243,8 +1351,9 @@ static int fts5RenameMethod( ** Flush the contents of the pending-terms table to disk. */ static int fts5SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){ - int rc = SQLITE_OK; - return rc; + Fts5Table *pTab = (Fts5Table*)pVtab; + 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. */ 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. */ static int fts5RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){ - return SQLITE_OK; + Fts5Table *pTab = (Fts5Table*)pVtab; + fts5CheckTransactionState(pTab, FTS5_ROLLBACKTO, iSavepoint); + return sqlite3Fts5IndexRollback(pTab->pIndex); } /* diff --git a/ext/fts5/fts5Int.h b/ext/fts5/fts5Int.h index 07903abf83..4ae110fd19 100644 --- a/ext/fts5/fts5Int.h +++ b/ext/fts5/fts5Int.h @@ -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_ASC 0x0002 /* Docs in ascending rowid order */ -#define FTS5INDEX_QUERY_MATCH 0x0004 /* Use the iMatch arg to Next() */ /* ** Create/destroy an Fts5Index object. @@ -230,22 +230,15 @@ void sqlite3Fts5IndexBeginWrite( /* ** Flush any data stored in the in-memory hash tables to the database. -** -** This is called whenever (a) the main transaction is committed or (b) a -** new sub-transaction is opened. +** If the bCommit flag is true, also close any open blob handles. */ -void sqlite3Fts5IndexFlush(Fts5Index *p); - -int sqlite3Fts5IndexSync(Fts5Index *p); +int sqlite3Fts5IndexSync(Fts5Index *p, int bCommit); /* ** 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 ** table may have changed on disk. So any in-memory caches of %_data ** 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); @@ -256,9 +249,10 @@ int sqlite3Fts5IndexErrcode(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. @@ -266,14 +260,23 @@ void sqlite3Fts5IndexAverages(Fts5Index *p, int bSet, int nAvg, int *aAvg); u64 sqlite3Fts5IndexCksum(Fts5Config*,i64,int,int,const char*,int); 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*); +/* +** 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); -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); /* diff --git a/ext/fts5/fts5_aux.c b/ext/fts5/fts5_aux.c index d378bb67f4..85bad5c496 100644 --- a/ext/fts5/fts5_aux.c +++ b/ext/fts5/fts5_aux.c @@ -745,9 +745,10 @@ static void fts5TestFunction( memset(&s, 0, sizeof(Fts5Buffer)); 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( zReq==0 && nCol>1 ) sqlite3Fts5BufferAppendPrintf(&rc, &s, "{"); for(i=0; rc==SQLITE_OK && i1 ) 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") ){ + nCol = pApi->xColumnCount(pFts); 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( zReq==0 && nCol>1 ) sqlite3Fts5BufferAppendPrintf(&rc, &s, "{"); for(i=0; rc==SQLITE_OK && i1 ) 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") ){ for(i=0; rc==SQLITE_OK && ixPhraseCount(pFts); if( 0==zReq || 0==sqlite3_stricmp(zReq, "phrasecount") ){ 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( nPhrase==1 ){ 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") ){ int bParen = 0; Fts5Buffer s3; memset(&s3, 0, sizeof(s3)); - for(i=0; ipReader ){ + /* 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 ** the blob_reopen() API to reseek the existing blob handle. */ @@ -762,8 +772,6 @@ sqlite3_free(buf.p); rc = sqlite3_blob_open(pConfig->db, pConfig->zDb, p->zDataTbl, "block", iRowid, 0, &p->pReader ); - }else{ - rc = sqlite3_blob_reopen(p->pReader, iRowid); } if( rc ) fts5MissingData(); @@ -2482,6 +2490,25 @@ static Fts5PendingDoclist *fts5PendingList(Fts5Index *p, int iHash){ 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 ** with buffer (nOld/pOld). @@ -3145,21 +3172,10 @@ static void fts5FlushOneHash(Fts5Index *p, int iHash, int *pnLeaf){ 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. */ -void sqlite3Fts5IndexFlush(Fts5Index *p){ +static void fts5IndexFlush(Fts5Index *p){ Fts5Config *pConfig = p->pConfig; int i; /* Used to iterate through indexes */ int nLeaf = 0; /* Number of leaves written */ @@ -3175,12 +3191,23 @@ void sqlite3Fts5IndexFlush(Fts5Index *p){ 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. */ -int sqlite3Fts5IndexSync(Fts5Index *p){ - sqlite3Fts5IndexFlush(p); - fts5CloseReader(p); +int sqlite3Fts5IndexSync(Fts5Index *p, int bCommit){ + fts5IndexFlush(p); + if( bCommit ) fts5CloseReader(p); return p->rc; } @@ -3192,6 +3219,7 @@ int sqlite3Fts5IndexSync(Fts5Index *p){ */ int sqlite3Fts5IndexRollback(Fts5Index *p){ fts5CloseReader(p); + fts5IndexDiscardData(p); return SQLITE_OK; } diff --git a/manifest b/manifest index 476c18f4f9..f539440020 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Use\sdoclist\sindexes\sfor\sAND\squeries\sas\swell\sas\sphrases. -D 2014-08-05T19:35:20.490 +C Add\ssupport\sfor\ssavepoints\sto\sfts5. +D 2014-08-06T16:30:21.057 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in b03432313a3aad96c706f8164fb9f5307eaf19f5 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/UnicodeData.txt cd07314edb62d49fde34debdaf92fa2aa69011e7 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/fts5Int.h aef50f3078e60707aeb2e4b2787d8c5eecdd02dc -F ext/fts5/fts5_aux.c 366057c7186bc3615deb5ecc0ff61de50b6d2dbc +F ext/fts5/fts5Int.h 410001da21bcc3d09b4290d4858352d0985ac7a6 +F ext/fts5/fts5_aux.c 31e581413ecab0962ce2b37468f9f658f36f4b0e F ext/fts5/fts5_buffer.c 248c61ac9fec001602efc72a45704f3b8d367c00 F ext/fts5/fts5_config.c f4ebf143e141b8c77355e3b15aba81b7be51d710 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/fts5parse.y 777da8e5819f75c217982c79c29d014c293acac9 F ext/icu/README.txt d9fbbad0c2f647c3fdf715fc9fd64af53aedfc43 @@ -603,6 +603,7 @@ F test/fts5ae.test cb37b3135a00d3afd5492ec534ecf654be5ff69e F test/fts5af.test 9ebe23aa3875896076952c7bc6e8308813a63c74 F test/fts5ag.test 0747bf3bade16d5165810cf891f875933b28b420 F test/fts5ah.test 009b993a9b7ebc43f84c10e53bd778b1dc8ffbe7 +F test/fts5ai.test 4dee71c23ddbcf2b0fc5d5586f241002b883c10e F test/fts5ea.test ff43b40f8879ba50b82def70f2ab67c195d1a1d4 F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d F test/func.test ae97561957aba6ca9e3a7b8a13aac41830d701ef @@ -770,7 +771,7 @@ F test/pagesize.test 1dd51367e752e742f58e861e65ed7390603827a0 F test/pcache.test b09104b03160aca0d968d99e8cd2c5b1921a993d F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025 F test/percentile.test b98fc868d71eb5619d42a1702e9ab91718cbed54 -F test/permutations.test 542edb965245565d06b9284e708f17bb93d70691 +F test/permutations.test 9875e7bacd0ab0cf78525e4b2d287840f284599b F test/pragma.test adb21a90875bc54a880fa939c4d7c46598905aa0 F test/pragma2.test aea7b3d82c76034a2df2b38a13745172ddc0bc13 F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552 @@ -1199,7 +1200,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 d028ba6589f3122b635474c2683c0f93d5bc6c7c -R df749c2987e3f7fa39a4c1c54f5a22e6 +P 5d38e6edc40ef188fbf96505073797036aa6783a +R e4475b88a5ed55985c58ff03d579a6b6 U dan -Z 78f1e7641fc2b68987e4a3c99853c1c0 +Z 1737719499cd3c712a0cb60804b1642b diff --git a/manifest.uuid b/manifest.uuid index 41e7ea9f15..e8347f8205 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5d38e6edc40ef188fbf96505073797036aa6783a \ No newline at end of file +3b19eba042bb2eeb1be60f8d58ebaa0a045d6a5c \ No newline at end of file diff --git a/test/fts5ai.test b/test/fts5ai.test new file mode 100644 index 0000000000..705ca15988 --- /dev/null +++ b/test/fts5ai.test @@ -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 + diff --git a/test/permutations.test b/test/permutations.test index 41659ef898..550028ea32 100644 --- a/test/permutations.test +++ b/test/permutations.test @@ -226,7 +226,7 @@ test_suite "fts5" -prefix "" -description { All FTS5 tests. } -files { 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 {