]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix a spurious SQLITE_CONSTRAINT error that may be returned by an incr-merge operation.
authordan <dan@noemail.net>
Fri, 23 Mar 2012 18:26:11 +0000 (18:26 +0000)
committerdan <dan@noemail.net>
Fri, 23 Mar 2012 18:26:11 +0000 (18:26 +0000)
FossilOrigin-Name: ed7c17ea165f6348506bd23ebc58c427bb65d697

ext/fts3/fts3.c
ext/fts3/fts3Int.h
ext/fts3/fts3_write.c
manifest
manifest.uuid

index 421052b9377bb9a83212ec4f57a0ec8613f2257d..ad0cb36da9de91a985569b8e43215ae835b84ab0 100644 (file)
@@ -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;
 }
 
 /*
index e847aad15d2ebd0e0c4d6c1d2d0909adf085c50c..f84d15d196e2d6e774e650a27054d041c5b07818 100644 (file)
@@ -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 */
index e755c53cc6ceeec6e2cfc5b730e00ea399f946d8..30f5e666eb5fc1f436dec849430b653e46928b06 100644 (file)
@@ -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 && i<nIdx; i++){
+    if( aIdx[i]!=i ){
+      sqlite3_bind_int(pUpdate, 3, aIdx[i]);
+      sqlite3_bind_int(pUpdate, 1, i);
+      sqlite3_step(pUpdate);
+      rc = sqlite3_reset(pUpdate);
+    }
   }
+  p->bIgnoreSavepoint = 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;
 }
index aa8e07fecd59f5feaf83abb42dff311c3cd8dca0..a6dafc26fe8f4fd63749d7b5de37fd19a4a21265 100644 (file)
--- 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
index 2ffc66650d445ce6ada4c1d4a38bb4f6778f4590..0886bc8716761c149bb244d2b10e10dd6c0a040e 100644 (file)
@@ -1 +1 @@
-1c72cecc6bf5be2a5c04ad6214a6bac22a29f860
\ No newline at end of file
+ed7c17ea165f6348506bd23ebc58c427bb65d697
\ No newline at end of file