From d59de73e27528c79ed63bf42993512a2a1a60d55 Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 23 Mar 2012 18:26:11 +0000 Subject: [PATCH] Fix a spurious SQLITE_CONSTRAINT error that may be returned by an incr-merge operation. FossilOrigin-Name: ed7c17ea165f6348506bd23ebc58c427bb65d697 --- ext/fts3/fts3.c | 6 +++- ext/fts3/fts3Int.h | 3 +- ext/fts3/fts3_write.c | 83 ++++++++++++++++++++++++++++++++++++------- manifest | 16 ++++----- manifest.uuid | 2 +- 5 files changed, 87 insertions(+), 23 deletions(-) diff --git a/ext/fts3/fts3.c b/ext/fts3/fts3.c index 421052b937..ad0cb36da9 100644 --- a/ext/fts3/fts3.c +++ b/ext/fts3/fts3.c @@ -3412,11 +3412,15 @@ static int fts3RenameMethod( ** Flush the contents of the pending-terms table to disk. */ static int fts3SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){ + int rc = SQLITE_OK; UNUSED_PARAMETER(iSavepoint); assert( ((Fts3Table *)pVtab)->inTransaction ); assert( ((Fts3Table *)pVtab)->mxSavepoint < iSavepoint ); TESTONLY( ((Fts3Table *)pVtab)->mxSavepoint = iSavepoint ); - return fts3SyncMethod(pVtab); + if( ((Fts3Table *)pVtab)->bIgnoreSavepoint==0 ){ + rc = fts3SyncMethod(pVtab); + } + return rc; } /* diff --git a/ext/fts3/fts3Int.h b/ext/fts3/fts3Int.h index e847aad15d..f84d15d196 100644 --- a/ext/fts3/fts3Int.h +++ b/ext/fts3/fts3Int.h @@ -200,7 +200,7 @@ struct Fts3Table { /* Precompiled statements used by the implementation. Each of these ** statements is run and reset within a single virtual table API call. */ - sqlite3_stmt *aStmt[35]; + sqlite3_stmt *aStmt[36]; char *zReadExprlist; char *zWriteExprlist; @@ -209,6 +209,7 @@ struct Fts3Table { u8 bHasStat; /* True if %_stat table exists */ u8 bHasDocsize; /* True if %_docsize table exists */ u8 bDescIdx; /* True if doclists are in reverse order */ + u8 bIgnoreSavepoint; /* True to ignore xSavepoint invocations */ int nPgsz; /* Page size for host database */ char *zSegmentsTbl; /* Name of %_segments table */ sqlite3_blob *pSegments; /* Blob handle open on %_segments table */ diff --git a/ext/fts3/fts3_write.c b/ext/fts3/fts3_write.c index e755c53cc6..30f5e666eb 100644 --- a/ext/fts3/fts3_write.c +++ b/ext/fts3/fts3_write.c @@ -259,10 +259,11 @@ struct SegmentNode { #define SQL_FIND_MERGE_LEVEL 28 #define SQL_MAX_LEAF_NODE_ESTIMATE 29 #define SQL_DELETE_SEGDIR_ENTRY 30 -#define SQL_SHIFT_SEGDIR_ENTRIES 31 +#define SQL_SHIFT_SEGDIR_ENTRY 31 #define SQL_SELECT_SEGDIR 32 #define SQL_CHOMP_SEGDIR 33 #define SQL_SEGMENT_IS_APPENDABLE 34 +#define SQL_SELECT_INDEXES 35 /* ** This function is used to obtain an SQLite prepared statement handle @@ -337,10 +338,10 @@ static int fts3SqlStmt( ** Delete the %_segdir entry on absolute level :1 with index :2. */ /* 30 */ "DELETE FROM %Q.'%q_segdir' WHERE level = ? AND idx = ?", -/* SQL_SHIFT_SEGDIR_ENTRIES -** Reduce by one the idx values of all segments on absolute level :1 with -** an index greater than :2. */ -/* 31 */ "UPDATE %Q.'%q_segdir' SET idx = idx - 1 WHERE level = ? AND idx>:2", +/* SQL_SHIFT_SEGDIR_ENTRY +** Modify the idx value for the segment with idx=:3 on absolute level :2 +** to :1. */ +/* 31 */ "UPDATE %Q.'%q_segdir' SET idx = ? WHERE level=? AND idx=?", /* SQL_SELECT_SEGDIR ** Read a single entry from the %_segdir table. The entry from absolute @@ -357,7 +358,11 @@ static int fts3SqlStmt( /* SQL_SEGMENT_IS_APPENDABLE ** Return a single row if the segment with end_block=? is appendable. Or ** no rows otherwise. */ -/* 34 */ "SELECT 1 FROM %Q.'%q_segments' WHERE blockid=? AND block IS NULL" +/* 34 */ "SELECT 1 FROM %Q.'%q_segments' WHERE blockid=? AND block IS NULL", + +/* SQL_SELECT_INDEXES +** Return the list of valid segment indexes for absolute level ? */ +/* 35 */ "SELECT idx FROM %Q.'%q_segdir' WHERE level=? ORDER BY 1 ASC" }; int rc = SQLITE_OK; sqlite3_stmt *pStmt; @@ -4113,7 +4118,6 @@ static int fts3RemoveSegdirEntry( ){ int rc; /* Return code */ sqlite3_stmt *pDelete = 0; /* DELETE statement */ - sqlite3_stmt *pUpdate = 0; /* UPDATE statement */ rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_ENTRY, &pDelete, 0); if( rc==SQLITE_OK ){ @@ -4123,16 +4127,67 @@ static int fts3RemoveSegdirEntry( rc = sqlite3_reset(pDelete); } + return rc; +} + +/* +** One or more segments have just been removed from absolute level iAbsLevel. +** Update the 'idx' values of the remaining segments in the level so that +** the idx values are a contiguous sequence starting from 0. +*/ +static int fts3RepackSegdirLevel( + Fts3Table *p, /* FTS3 table handle */ + sqlite3_int64 iAbsLevel /* Absolute level to repack */ +){ + int rc; /* Return code */ + int *aIdx = 0; /* Array of remaining idx values */ + int nIdx = 0; /* Valid entries in aIdx[] */ + int nAlloc = 0; /* Allocated size of aIdx[] */ + int i; /* Iterator variable */ + sqlite3_stmt *pSelect = 0; /* Select statement to read idx values */ + sqlite3_stmt *pUpdate = 0; /* Update statement to modify idx values */ + + rc = fts3SqlStmt(p, SQL_SELECT_INDEXES, &pSelect, 0); if( rc==SQLITE_OK ){ - rc = fts3SqlStmt(p, SQL_SHIFT_SEGDIR_ENTRIES, &pUpdate, 0); + int rc2; + sqlite3_bind_int64(pSelect, 1, iAbsLevel); + while( SQLITE_ROW==sqlite3_step(pSelect) ){ + if( nIdx>=nAlloc ){ + int *aNew; + nAlloc += 16; + aNew = sqlite3_realloc(aIdx, nAlloc*sizeof(int)); + if( !aNew ){ + rc = SQLITE_NOMEM; + break; + } + aIdx = aNew; + } + aIdx[nIdx++] = sqlite3_column_int(pSelect, 0); + } + rc2 = sqlite3_reset(pSelect); + if( rc==SQLITE_OK ) rc = rc2; + } + + if( rc==SQLITE_OK ){ + rc = fts3SqlStmt(p, SQL_SHIFT_SEGDIR_ENTRY, &pUpdate, 0); } if( rc==SQLITE_OK ){ - sqlite3_bind_int64(pUpdate, 1, iAbsLevel); - sqlite3_bind_int(pUpdate, 2, iIdx); - sqlite3_step(pUpdate); - rc = sqlite3_reset(pUpdate); + sqlite3_bind_int64(pUpdate, 2, iAbsLevel); + } + + assert( p->bIgnoreSavepoint==0 ); + p->bIgnoreSavepoint = 1; + for(i=0; rc==SQLITE_OK && ibIgnoreSavepoint = 0; + sqlite3_free(aIdx); return rc; } @@ -4335,6 +4390,10 @@ static int fts3IncrmergeChomp( } } + if( rc==SQLITE_OK && nRem!=pCsr->nSegment ){ + rc = fts3RepackSegdirLevel(p, iAbsLevel); + } + *pnRem = nRem; return rc; } diff --git a/manifest b/manifest index aa8e07fecd..a6dafc26fe 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sa\stest\sto\sverify\sthat\ssqlite3_total_changes()\sworks\swith\sincr-merge\soperations. -D 2012-03-23T15:38:43.298 +C Fix\sa\sspurious\sSQLITE_CONSTRAINT\serror\sthat\smay\sbe\sreturned\sby\san\sincr-merge\soperation. +D 2012-03-23T18:26:11.608 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2f37e468503dbe79d35c9f6dffcf3fae1ae9ec20 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -63,9 +63,9 @@ F ext/fts3/README.content fdc666a70d5257a64fee209f97cf89e0e6e32b51 F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a F ext/fts3/README.tokenizers 998756696647400de63d5ba60e9655036cb966e9 F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d -F ext/fts3/fts3.c a62e09140c00f9c401efca661e7f2ae9909194f6 +F ext/fts3/fts3.c c47bb6fe7a6bde82cbdf4c504302221710699d64 F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe -F ext/fts3/fts3Int.h caa745f80405bc0c0a45a2f83e120d5a2c13753c +F ext/fts3/fts3Int.h 5fe1651db88206ca68f421cf62bb8501395677a3 F ext/fts3/fts3_aux.c 5205182bd8f372782597888156404766edf5781e F ext/fts3/fts3_expr.c dbc7ba4c3a6061adde0f38ed8e9b349568299551 F ext/fts3/fts3_hash.c 8dd2d06b66c72c628c2732555a32bc0943114914 @@ -78,7 +78,7 @@ F ext/fts3/fts3_test.c 6b7cc68aef4efb084e1449f7d20c4b20d3bdf6b4 F ext/fts3/fts3_tokenizer.c 3da7254a9881f7e270ab28e2004e0d22b3212bce F ext/fts3/fts3_tokenizer.h 66dec98e365854b6cd2d54f1a96bb6d428fc5a68 F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004 -F ext/fts3/fts3_write.c 8791a3dae9d1433261800e7d36208d3e88ffa5bc +F ext/fts3/fts3_write.c e3b750530132b3237aed3e5f008845cc4d7865f9 F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9 F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100 F ext/icu/README.txt bf8461d8cdc6b8f514c080e4e10dc3b2bbdfefa9 @@ -997,7 +997,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -P 96ed47493b3d46344fd2105642f31690aee06674 -R f6fdda04671e81d1436014dc3e6ce1ef +P 1c72cecc6bf5be2a5c04ad6214a6bac22a29f860 +R c0998f3b8bc74543bb7322ba65e1257e U dan -Z ca34b2031de3681fa84c177cb5bd2b1e +Z 3e48c8e93d6fd57a390b8a97532e70ea diff --git a/manifest.uuid b/manifest.uuid index 2ffc66650d..0886bc8716 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1c72cecc6bf5be2a5c04ad6214a6bac22a29f860 \ No newline at end of file +ed7c17ea165f6348506bd23ebc58c427bb65d697 \ No newline at end of file -- 2.47.2