/ Check-in [7d7d633c71]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Fix a problem causing the fts3 integrity-check to fail if run inside a transaction. Cherrypick of [3b925189a75e].
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | branch-3.8.6
Files: files | file ages | folders
SHA1: 7d7d633c71bb36bed98bc2c77d3268cc26fbac3e
User & Date: dan 2015-05-20 20:34:37
Context
2015-05-20
20:50
Fix a problem in test file e_reindex.test. Cherrypick of [5b3de9390f2f]. check-in: 80633682d7 user: dan tags: branch-3.8.6
20:34
Fix a problem causing the fts3 integrity-check to fail if run inside a transaction. Cherrypick of [3b925189a75e]. check-in: 7d7d633c71 user: dan tags: branch-3.8.6
20:30
Ensure that tables names are dequoted exactly once by the trigger and FK logic. Cherrypick of [59e92bd9521f] and [9d887b92f808]. check-in: bd357739d7 user: dan tags: branch-3.8.6
2015-04-23
11:52
Fix a problem causing the fts3 integrity-check to fail if run inside a transaction. check-in: 3b925189a7 user: dan tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to ext/fts3/fts3.c.

  2766   2766     ** for the pending-terms. If this is a scan, then this call must be being
  2767   2767     ** made by an fts4aux module, not an FTS table. In this case calling
  2768   2768     ** Fts3SegReaderPending might segfault, as the data structures used by 
  2769   2769     ** fts4aux are not completely populated. So it's easiest to filter these
  2770   2770     ** calls out here.  */
  2771   2771     if( iLevel<0 && p->aIndex ){
  2772   2772       Fts3SegReader *pSeg = 0;
  2773         -    rc = sqlite3Fts3SegReaderPending(p, iIndex, zTerm, nTerm, isPrefix, &pSeg);
         2773  +    rc = sqlite3Fts3SegReaderPending(p, iIndex, zTerm, nTerm, isPrefix||isScan, &pSeg);
  2774   2774       if( rc==SQLITE_OK && pSeg ){
  2775   2775         rc = fts3SegReaderCursorAppend(pCsr, pSeg);
  2776   2776       }
  2777   2777     }
  2778   2778   
  2779   2779     if( iLevel!=FTS3_SEGCURSOR_PENDING ){
  2780   2780       if( rc==SQLITE_OK ){

Changes to ext/fts3/fts3_write.c.

   322    322   /* 21 */  "SELECT size FROM %Q.'%q_docsize' WHERE docid=?",
   323    323   /* 22 */  "SELECT value FROM %Q.'%q_stat' WHERE id=?",
   324    324   /* 23 */  "REPLACE INTO %Q.'%q_stat' VALUES(?,?)",
   325    325   /* 24 */  "",
   326    326   /* 25 */  "",
   327    327   
   328    328   /* 26 */ "DELETE FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?",
   329         -/* 27 */ "SELECT DISTINCT level / (1024 * ?) FROM %Q.'%q_segdir'",
          329  +/* 27 */ "SELECT ? UNION SELECT level / (1024 * ?) FROM %Q.'%q_segdir'",
   330    330   
   331    331   /* This statement is used to determine which level to read the input from
   332    332   ** when performing an incremental merge. It returns the absolute level number
   333    333   ** of the oldest level in the db that contains at least ? segments. Or,
   334    334   ** if no level in the FTS index contains more than ? segments, the statement
   335    335   ** returns zero rows.  */
   336    336   /* 28 */ "SELECT level FROM %Q.'%q_segdir' GROUP BY level HAVING count(*)>=?"
................................................................................
  3437   3437     int bSeenDone = 0;
  3438   3438     int rc;
  3439   3439     sqlite3_stmt *pAllLangid = 0;
  3440   3440   
  3441   3441     rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0);
  3442   3442     if( rc==SQLITE_OK ){
  3443   3443       int rc2;
  3444         -    sqlite3_bind_int(pAllLangid, 1, p->nIndex);
         3444  +    sqlite3_bind_int(pAllLangid, 1, p->iPrevLangid);
         3445  +    sqlite3_bind_int(pAllLangid, 2, p->nIndex);
  3445   3446       while( sqlite3_step(pAllLangid)==SQLITE_ROW ){
  3446   3447         int i;
  3447   3448         int iLangid = sqlite3_column_int(pAllLangid, 0);
  3448   3449         for(i=0; rc==SQLITE_OK && i<p->nIndex; i++){
  3449   3450           rc = fts3SegmentMerge(p, iLangid, i, FTS3_SEGCURSOR_ALL);
  3450   3451           if( rc==SQLITE_DONE ){
  3451   3452             bSeenDone = 1;
................................................................................
  4769   4770     i = pHint->n-2;
  4770   4771     while( i>0 && (pHint->a[i-1] & 0x80) ) i--;
  4771   4772     while( i>0 && (pHint->a[i-1] & 0x80) ) i--;
  4772   4773   
  4773   4774     pHint->n = i;
  4774   4775     i += sqlite3Fts3GetVarint(&pHint->a[i], piAbsLevel);
  4775   4776     i += fts3GetVarint32(&pHint->a[i], pnInput);
  4776         -  if( i!=nHint ) return SQLITE_CORRUPT_VTAB;
         4777  +  if( i!=nHint ) return FTS_CORRUPT_VTAB;
  4777   4778   
  4778   4779     return SQLITE_OK;
  4779   4780   }
  4780   4781   
  4781   4782   
  4782   4783   /*
  4783   4784   ** Attempt an incremental merge that writes nMerge leaf blocks.
................................................................................
  5137   5138     u64 cksum2 = 0;                 /* Checksum based on %_content contents */
  5138   5139     sqlite3_stmt *pAllLangid = 0;   /* Statement to return all language-ids */
  5139   5140   
  5140   5141     /* This block calculates the checksum according to the FTS index. */
  5141   5142     rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0);
  5142   5143     if( rc==SQLITE_OK ){
  5143   5144       int rc2;
  5144         -    sqlite3_bind_int(pAllLangid, 1, p->nIndex);
         5145  +    sqlite3_bind_int(pAllLangid, 1, p->iPrevLangid);
         5146  +    sqlite3_bind_int(pAllLangid, 2, p->nIndex);
  5145   5147       while( rc==SQLITE_OK && sqlite3_step(pAllLangid)==SQLITE_ROW ){
  5146   5148         int iLangid = sqlite3_column_int(pAllLangid, 0);
  5147   5149         int i;
  5148   5150         for(i=0; i<p->nIndex; i++){
  5149   5151           cksum1 = cksum1 ^ fts3ChecksumIndex(p, iLangid, i, &rc);
  5150   5152         }
  5151   5153       }
  5152   5154       rc2 = sqlite3_reset(pAllLangid);
  5153   5155       if( rc==SQLITE_OK ) rc = rc2;
  5154   5156     }
  5155   5157   
  5156   5158     /* This block calculates the checksum according to the %_content table */
  5157         -  rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0);
  5158   5159     if( rc==SQLITE_OK ){
  5159   5160       sqlite3_tokenizer_module const *pModule = p->pTokenizer->pModule;
  5160   5161       sqlite3_stmt *pStmt = 0;
  5161   5162       char *zSql;
  5162   5163      
  5163   5164       zSql = sqlite3_mprintf("SELECT %s" , p->zReadExprlist);
  5164   5165       if( !zSql ){
................................................................................
  5247   5248   */
  5248   5249   static int fts3DoIntegrityCheck(
  5249   5250     Fts3Table *p                    /* FTS3 table handle */
  5250   5251   ){
  5251   5252     int rc;
  5252   5253     int bOk = 0;
  5253   5254     rc = fts3IntegrityCheck(p, &bOk);
  5254         -  if( rc==SQLITE_OK && bOk==0 ) rc = SQLITE_CORRUPT_VTAB;
         5255  +  if( rc==SQLITE_OK && bOk==0 ) rc = FTS_CORRUPT_VTAB;
  5255   5256     return rc;
  5256   5257   }
  5257   5258   
  5258   5259   /*
  5259   5260   ** Handle a 'special' INSERT of the form:
  5260   5261   **
  5261   5262   **   "INSERT INTO tbl(tbl) VALUES(<expr>)"

Changes to test/fts4check.test.

   174    174     db close
   175    175     sqlite3 db test.db
   176    176     catchsql {
   177    177       INSERT INTO t4(t4) VALUES('integrity-check');
   178    178     }
   179    179   } {1 {database disk image is malformed}}
   180    180   reset_db
          181  +
          182  +#--------------------------------------------------------------------------
          183  +# Test case 5.*
          184  +#
          185  +# Test that the integrity-check works if there is uncommitted data.
          186  +#
          187  +do_execsql_test 5.0 {
          188  +  BEGIN;
          189  +  CREATE VIRTUAL TABLE t5 USING fts4(a, prefix="1,2,3");
          190  +  INSERT INTO t5 VALUES('And down by Kosiosko, where the reed-banks sweep');
          191  +  INSERT INTO t5 VALUES('and sway, and the rolling plains are wide, the');
          192  +  INSERT INTO t5 VALUES('man from snowy river is a household name today,');
          193  +  INSERT INTO t5 VALUES('and the stockmen tell the story of his ride');
          194  +}
          195  +
          196  +do_execsql_test 5.1 {
          197  +  INSERT INTO t5(t5) VALUES('integrity-check');
          198  +} {}
          199  +
          200  +do_catchsql_test 5.2 {
          201  +  INSERT INTO t5_content VALUES(5, 'his hardy mountain pony');
          202  +  INSERT INTO t5(t5) VALUES('integrity-check');
          203  +} {1 {database disk image is malformed}}
          204  +
          205  +do_execsql_test 5.3 ROLLBACK
          206  +
          207  +do_execsql_test 5.4 {
          208  +  CREATE VIRTUAL TABLE t5 USING fts4(a, prefix="1,2,3");
          209  +  INSERT INTO t5(t5) VALUES('integrity-check');
          210  +} {}
   181    211   
   182    212   finish_test
   183    213   

Changes to test/trace2.test.

   139    139       "-- SELECT level, idx, end_block FROM 'main'.'x1_segdir' WHERE level BETWEEN ? AND ? ORDER BY level DESC, idx ASC"
   140    140     }
   141    141   
   142    142     do_trace_test 2.3 {
   143    143       INSERT INTO x1(x1) VALUES('optimize');
   144    144     } {
   145    145       "INSERT INTO x1(x1) VALUES('optimize');"
   146         -    "-- SELECT DISTINCT level / (1024 * ?) FROM 'main'.'x1_segdir'"
          146  +    "-- SELECT ? UNION SELECT level / (1024 * ?) FROM 'main'.'x1_segdir'"
   147    147       "-- SELECT idx, start_block, leaves_end_block, end_block, root FROM 'main'.'x1_segdir' WHERE level BETWEEN ? AND ?ORDER BY level DESC, idx ASC"
   148    148       "-- SELECT max(level) FROM 'main'.'x1_segdir' WHERE level BETWEEN ? AND ?"
   149    149       "-- SELECT coalesce((SELECT max(blockid) FROM 'main'.'x1_segments') + 1, 1)"
   150    150       "-- DELETE FROM 'main'.'x1_segdir' WHERE level BETWEEN ? AND ?"
   151    151       "-- REPLACE INTO 'main'.'x1_segdir' VALUES(?,?,?,?,?,?)"
   152    152     }
   153    153   }
   154    154   
   155    155   finish_test