/ Check-in [c67a52c356]
Login

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

Overview
Comment:Changes to FTS to ensure that it does not access the database from within the xConnect method.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: c67a52c356416cc200f51f9168d942e78db11d34
User & Date: dan 2014-03-12 19:20:36
Context
2014-03-12
19:38
Fix an obscure bug causing sqlite3_close() to fail if there are virtual tables on the disconnect list when it is called. check-in: 6504aa47a8 user: dan tags: trunk
19:20
Changes to FTS to ensure that it does not access the database from within the xConnect method. check-in: c67a52c356 user: dan tags: trunk
12:44
Prevent the rtree module from reading sqlite_stat1 data from the wrong database. check-in: 7ce03c1b55 user: dan tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to ext/fts3/fts3.c.

  1406   1406       rc = fts3CreateTables(p);
  1407   1407     }
  1408   1408   
  1409   1409     /* Check to see if a legacy fts3 table has been "upgraded" by the
  1410   1410     ** addition of a %_stat table so that it can use incremental merge.
  1411   1411     */
  1412   1412     if( !isFts4 && !isCreate ){
  1413         -    int rc2 = SQLITE_OK;
  1414         -    fts3DbExec(&rc2, db, "SELECT 1 FROM %Q.'%q_stat' WHERE id=2",
  1415         -               p->zDb, p->zName);
  1416         -    if( rc2==SQLITE_OK ) p->bHasStat = 1;
         1413  +    p->bHasStat = 2;
  1417   1414     }
  1418   1415   
  1419   1416     /* Figure out the page-size for the database. This is required in order to
  1420   1417     ** estimate the cost of loading large doclists from the database.  */
  1421   1418     fts3DatabasePageSize(&rc, p);
  1422   1419     p->nNodeSize = p->nPgsz-35;
  1423   1420   
................................................................................
  3316   3313       if( A>(int)nMinMerge ) rc = sqlite3Fts3Incrmerge(p, A, 8);
  3317   3314     }
  3318   3315     sqlite3Fts3SegmentsClose(p);
  3319   3316     return rc;
  3320   3317   }
  3321   3318   
  3322   3319   /*
  3323         -** Implementation of xBegin() method. This is a no-op.
         3320  +** If it is currently unknown whether or not the FTS table has an %_stat
         3321  +** table (if p->bHasStat==2), attempt to determine this (set p->bHasStat
         3322  +** to 0 or 1). Return SQLITE_OK if successful, or an SQLite error code
         3323  +** if an error occurs.
         3324  +*/
         3325  +static int fts3SetHasStat(Fts3Table *p){
         3326  +  int rc = SQLITE_OK;
         3327  +  if( p->bHasStat==2 ){
         3328  +    const char *zFmt ="SELECT 1 FROM %Q.sqlite_master WHERE tbl_name='%q_stat'";
         3329  +    char *zSql = sqlite3_mprintf(zFmt, p->zDb, p->zName);
         3330  +    if( zSql ){
         3331  +      sqlite3_stmt *pStmt = 0;
         3332  +      rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
         3333  +      if( rc==SQLITE_OK ){
         3334  +        int bHasStat = (sqlite3_step(pStmt)==SQLITE_ROW);
         3335  +        rc = sqlite3_finalize(pStmt);
         3336  +        if( rc==SQLITE_OK ) p->bHasStat = bHasStat;
         3337  +      }
         3338  +      sqlite3_free(zSql);
         3339  +    }else{
         3340  +      rc = SQLITE_NOMEM;
         3341  +    }
         3342  +  }
         3343  +  return rc;
         3344  +}
         3345  +
         3346  +/*
         3347  +** Implementation of xBegin() method. 
  3324   3348   */
  3325   3349   static int fts3BeginMethod(sqlite3_vtab *pVtab){
  3326   3350     Fts3Table *p = (Fts3Table*)pVtab;
  3327   3351     UNUSED_PARAMETER(pVtab);
  3328   3352     assert( p->pSegments==0 );
  3329   3353     assert( p->nPendingData==0 );
  3330   3354     assert( p->inTransaction!=1 );
  3331   3355     TESTONLY( p->inTransaction = 1 );
  3332   3356     TESTONLY( p->mxSavepoint = -1; );
  3333   3357     p->nLeafAdd = 0;
  3334         -  return SQLITE_OK;
         3358  +  return fts3SetHasStat(p);
  3335   3359   }
  3336   3360   
  3337   3361   /*
  3338   3362   ** Implementation of xCommit() method. This is a no-op. The contents of
  3339   3363   ** the pending-terms hash-table have already been flushed into the database
  3340   3364   ** by fts3SyncMethod().
  3341   3365   */
................................................................................
  3576   3600     sqlite3_vtab *pVtab,            /* Virtual table handle */
  3577   3601     const char *zName               /* New name of table */
  3578   3602   ){
  3579   3603     Fts3Table *p = (Fts3Table *)pVtab;
  3580   3604     sqlite3 *db = p->db;            /* Database connection */
  3581   3605     int rc;                         /* Return Code */
  3582   3606   
         3607  +  /* At this point it must be known if the %_stat table exists or not.
         3608  +  ** So bHasStat may not be 2.  */
         3609  +  rc = fts3SetHasStat(p);
         3610  +  
  3583   3611     /* As it happens, the pending terms table is always empty here. This is
  3584   3612     ** because an "ALTER TABLE RENAME TABLE" statement inside a transaction 
  3585   3613     ** always opens a savepoint transaction. And the xSavepoint() method 
  3586   3614     ** flushes the pending terms table. But leave the (no-op) call to
  3587   3615     ** PendingTermsFlush() in in case that changes.
  3588   3616     */
  3589   3617     assert( p->nPendingData==0 );
  3590         -  rc = sqlite3Fts3PendingTermsFlush(p);
         3618  +  if( rc==SQLITE_OK ){
         3619  +    rc = sqlite3Fts3PendingTermsFlush(p);
         3620  +  }
  3591   3621   
  3592   3622     if( p->zContentTbl==0 ){
  3593   3623       fts3DbExec(&rc, db,
  3594   3624         "ALTER TABLE %Q.'%q_content'  RENAME TO '%q_content';",
  3595   3625         p->zDb, p->zName, zName
  3596   3626       );
  3597   3627     }

Changes to ext/fts3/fts3Int.h.

   219    219     sqlite3_stmt *aStmt[37];
   220    220   
   221    221     char *zReadExprlist;
   222    222     char *zWriteExprlist;
   223    223   
   224    224     int nNodeSize;                  /* Soft limit for node size */
   225    225     u8 bFts4;                       /* True for FTS4, false for FTS3 */
   226         -  u8 bHasStat;                    /* True if %_stat table exists */
          226  +  u8 bHasStat;                    /* True if %_stat table exists (2==unknown) */
   227    227     u8 bHasDocsize;                 /* True if %_docsize table exists */
   228    228     u8 bDescIdx;                    /* True if doclists are in reverse order */
   229    229     u8 bIgnoreSavepoint;            /* True to ignore xSavepoint invocations */
   230    230     int nPgsz;                      /* Page size for host database */
   231    231     char *zSegmentsTbl;             /* Name of %_segments table */
   232    232     sqlite3_blob *pSegments;        /* Blob handle open on %_segments table */
   233    233   

Changes to ext/fts3/fts3_write.c.

  5266   5266     Fts3Table *p = (Fts3Table *)pVtab;
  5267   5267     int rc = SQLITE_OK;             /* Return Code */
  5268   5268     int isRemove = 0;               /* True for an UPDATE or DELETE */
  5269   5269     u32 *aSzIns = 0;                /* Sizes of inserted documents */
  5270   5270     u32 *aSzDel = 0;                /* Sizes of deleted documents */
  5271   5271     int nChng = 0;                  /* Net change in number of documents */
  5272   5272     int bInsertDone = 0;
         5273  +
         5274  +  /* At this point it must be known if the %_stat table exists or not.
         5275  +  ** So bHasStat may not be 2.  */
         5276  +  assert( p->bHasStat==0 || p->bHasStat==1 );
  5273   5277   
  5274   5278     assert( p->pSegments==0 );
  5275   5279     assert( 
  5276   5280         nArg==1                     /* DELETE operations */
  5277   5281      || nArg==(2 + p->nColumn + 3)  /* INSERT or UPDATE operations */
  5278   5282     );
  5279   5283   

Changes to test/fts3d.test.

   350    350   } {fts_content fts_segdir fts_segments}
   351    351   do_test fts3d-6.5 {
   352    352     db eval {
   353    353       ALTER TABLE fts RENAME TO xyz;
   354    354       SELECT name FROM sqlite_master WHERE name GLOB '???_*' ORDER BY 1;
   355    355     }
   356    356   } {xyz_content xyz_segdir xyz_segments}
          357  +
          358  +# ALTER TABLE RENAME on an FTS3 table following an incr-merge op.
          359  +#
          360  +do_test fts3d-6.6 {
          361  +  execsql { INSERT INTO xyz(xyz) VALUES('merge=2,2') }
          362  +  sqlite3 db test.db
          363  +  execsql { 
          364  +    ALTER TABLE xyz RENAME TO ott;
          365  +    SELECT name FROM sqlite_master WHERE name GLOB '???_*' ORDER BY 1;
          366  +  }
          367  +} {ott_content ott_segdir ott_segments ott_stat}
   357    368    
   358    369   
   359    370   finish_test