Back to index

lightning-sunbird  0.9+nobinonly
vacuum.c
Go to the documentation of this file.
00001 /*
00002 ** 2003 April 6
00003 **
00004 ** The author disclaims copyright to this source code.  In place of
00005 ** a legal notice, here is a blessing:
00006 **
00007 **    May you do good and not evil.
00008 **    May you find forgiveness for yourself and forgive others.
00009 **    May you share freely, never taking more than you give.
00010 **
00011 *************************************************************************
00012 ** This file contains code used to implement the VACUUM command.
00013 **
00014 ** Most of the code in this file may be omitted by defining the
00015 ** SQLITE_OMIT_VACUUM macro.
00016 **
00017 ** $Id: vacuum.c,v 1.59 2006/02/24 02:53:50 drh Exp $
00018 */
00019 #include "sqliteInt.h"
00020 #include "vdbeInt.h"
00021 #include "os.h"
00022 
00023 #ifndef SQLITE_OMIT_VACUUM
00024 /*
00025 ** Generate a random name of 20 character in length.
00026 */
00027 static void randomName(unsigned char *zBuf){
00028   static const unsigned char zChars[] =
00029     "abcdefghijklmnopqrstuvwxyz"
00030     "0123456789";
00031   int i;
00032   sqlite3Randomness(20, zBuf);
00033   for(i=0; i<20; i++){
00034     zBuf[i] = zChars[ zBuf[i]%(sizeof(zChars)-1) ];
00035   }
00036 }
00037 
00038 /*
00039 ** Execute zSql on database db. Return an error code.
00040 */
00041 static int execSql(sqlite3 *db, const char *zSql){
00042   sqlite3_stmt *pStmt;
00043   if( SQLITE_OK!=sqlite3_prepare(db, zSql, -1, &pStmt, 0) ){
00044     return sqlite3_errcode(db);
00045   }
00046   while( SQLITE_ROW==sqlite3_step(pStmt) ){}
00047   return sqlite3_finalize(pStmt);
00048 }
00049 
00050 /*
00051 ** Execute zSql on database db. The statement returns exactly
00052 ** one column. Execute this as SQL on the same database.
00053 */
00054 static int execExecSql(sqlite3 *db, const char *zSql){
00055   sqlite3_stmt *pStmt;
00056   int rc;
00057 
00058   rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);
00059   if( rc!=SQLITE_OK ) return rc;
00060 
00061   while( SQLITE_ROW==sqlite3_step(pStmt) ){
00062     rc = execSql(db, (char*)sqlite3_column_text(pStmt, 0));
00063     if( rc!=SQLITE_OK ){
00064       sqlite3_finalize(pStmt);
00065       return rc;
00066     }
00067   }
00068 
00069   return sqlite3_finalize(pStmt);
00070 }
00071 
00072 #endif
00073 
00074 /*
00075 ** The non-standard VACUUM command is used to clean up the database,
00076 ** collapse free space, etc.  It is modelled after the VACUUM command
00077 ** in PostgreSQL.
00078 **
00079 ** In version 1.0.x of SQLite, the VACUUM command would call
00080 ** gdbm_reorganize() on all the database tables.  But beginning
00081 ** with 2.0.0, SQLite no longer uses GDBM so this command has
00082 ** become a no-op.
00083 */
00084 void sqlite3Vacuum(Parse *pParse){
00085   Vdbe *v = sqlite3GetVdbe(pParse);
00086   if( v ){
00087     sqlite3VdbeAddOp(v, OP_Vacuum, 0, 0);
00088   }
00089   return;
00090 }
00091 
00092 /*
00093 ** This routine implements the OP_Vacuum opcode of the VDBE.
00094 */
00095 int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
00096   int rc = SQLITE_OK;     /* Return code from service routines */
00097 #ifndef SQLITE_OMIT_VACUUM
00098   const char *zFilename;  /* full pathname of the database file */
00099   int nFilename;          /* number of characters  in zFilename[] */
00100   char *zTemp = 0;        /* a temporary file in same directory as zFilename */
00101   Btree *pMain;           /* The database being vacuumed */
00102   Btree *pTemp;
00103   char *zSql = 0;
00104   int saved_flags;       /* Saved value of the db->flags */
00105   Db *pDb = 0;           /* Database to detach at end of vacuum */
00106 
00107   /* Save the current value of the write-schema flag before setting it. */
00108   saved_flags = db->flags;
00109   db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks;
00110 
00111   if( !db->autoCommit ){
00112     sqlite3SetString(pzErrMsg, "cannot VACUUM from within a transaction", 
00113        (char*)0);
00114     rc = SQLITE_ERROR;
00115     goto end_of_vacuum;
00116   }
00117 
00118   /* Get the full pathname of the database file and create a
00119   ** temporary filename in the same directory as the original file.
00120   */
00121   pMain = db->aDb[0].pBt;
00122   zFilename = sqlite3BtreeGetFilename(pMain);
00123   assert( zFilename );
00124   if( zFilename[0]=='\0' ){
00125     /* The in-memory database. Do nothing. Return directly to avoid causing
00126     ** an error trying to DETACH the vacuum_db (which never got attached)
00127     ** in the exit-handler.
00128     */
00129     return SQLITE_OK;
00130   }
00131   nFilename = strlen(zFilename);
00132   zTemp = sqliteMalloc( nFilename+100 );
00133   if( zTemp==0 ){
00134     rc = SQLITE_NOMEM;
00135     goto end_of_vacuum;
00136   }
00137   strcpy(zTemp, zFilename);
00138 
00139   /* The randomName() procedure in the following loop uses an excellent
00140   ** source of randomness to generate a name from a space of 1.3e+31 
00141   ** possibilities.  So unless the directory already contains on the order
00142   ** of 1.3e+31 files, the probability that the following loop will
00143   ** run more than once or twice is vanishingly small.  We are certain
00144   ** enough that this loop will always terminate (and terminate quickly)
00145   ** that we don't even bother to set a maximum loop count.
00146   */
00147   do {
00148     zTemp[nFilename] = '-';
00149     randomName((unsigned char*)&zTemp[nFilename+1]);
00150   } while( sqlite3OsFileExists(zTemp) );
00151 
00152   /* Attach the temporary database as 'vacuum_db'. The synchronous pragma
00153   ** can be set to 'off' for this file, as it is not recovered if a crash
00154   ** occurs anyway. The integrity of the database is maintained by a
00155   ** (possibly synchronous) transaction opened on the main database before
00156   ** sqlite3BtreeCopyFile() is called.
00157   **
00158   ** An optimisation would be to use a non-journaled pager.
00159   */
00160   zSql = sqlite3MPrintf("ATTACH '%q' AS vacuum_db;", zTemp);
00161   if( !zSql ){
00162     rc = SQLITE_NOMEM;
00163     goto end_of_vacuum;
00164   }
00165   rc = execSql(db, zSql);
00166   sqliteFree(zSql);
00167   zSql = 0;
00168   if( rc!=SQLITE_OK ) goto end_of_vacuum;
00169   pDb = &db->aDb[db->nDb-1];
00170   assert( strcmp(db->aDb[db->nDb-1].zName,"vacuum_db")==0 );
00171   pTemp = db->aDb[db->nDb-1].pBt;
00172   sqlite3BtreeSetPageSize(pTemp, sqlite3BtreeGetPageSize(pMain),
00173      sqlite3BtreeGetReserve(pMain));
00174   assert( sqlite3BtreeGetPageSize(pTemp)==sqlite3BtreeGetPageSize(pMain) );
00175   rc = execSql(db, "PRAGMA vacuum_db.synchronous=OFF");
00176   if( rc!=SQLITE_OK ){
00177     goto end_of_vacuum;
00178   }
00179 
00180 #ifndef SQLITE_OMIT_AUTOVACUUM
00181   sqlite3BtreeSetAutoVacuum(pTemp, sqlite3BtreeGetAutoVacuum(pMain));
00182 #endif
00183 
00184   /* Begin a transaction */
00185   rc = execSql(db, "BEGIN EXCLUSIVE;");
00186   if( rc!=SQLITE_OK ) goto end_of_vacuum;
00187 
00188   /* Query the schema of the main database. Create a mirror schema
00189   ** in the temporary database.
00190   */
00191   rc = execExecSql(db, 
00192       "SELECT 'CREATE TABLE vacuum_db.' || substr(sql,14,100000000) "
00193       "  FROM sqlite_master WHERE type='table' AND name!='sqlite_sequence'");
00194   if( rc!=SQLITE_OK ) goto end_of_vacuum;
00195   rc = execExecSql(db, 
00196       "SELECT 'CREATE INDEX vacuum_db.' || substr(sql,14,100000000)"
00197       "  FROM sqlite_master WHERE sql LIKE 'CREATE INDEX %' ");
00198   if( rc!=SQLITE_OK ) goto end_of_vacuum;
00199   rc = execExecSql(db, 
00200       "SELECT 'CREATE UNIQUE INDEX vacuum_db.' || substr(sql,21,100000000) "
00201       "  FROM sqlite_master WHERE sql LIKE 'CREATE UNIQUE INDEX %'");
00202   if( rc!=SQLITE_OK ) goto end_of_vacuum;
00203   rc = execExecSql(db, 
00204       "SELECT 'CREATE VIEW vacuum_db.' || substr(sql,13,100000000) "
00205       "  FROM sqlite_master WHERE type='view'"
00206   );
00207   if( rc!=SQLITE_OK ) goto end_of_vacuum;
00208 
00209   /* Loop through the tables in the main database. For each, do
00210   ** an "INSERT INTO vacuum_db.xxx SELECT * FROM xxx;" to copy
00211   ** the contents to the temporary database.
00212   */
00213   rc = execExecSql(db, 
00214       "SELECT 'INSERT INTO vacuum_db.' || quote(name) "
00215       "|| ' SELECT * FROM ' || quote(name) || ';'"
00216       "FROM sqlite_master "
00217       "WHERE type = 'table' AND name!='sqlite_sequence';"
00218   );
00219   if( rc!=SQLITE_OK ) goto end_of_vacuum;
00220 
00221   /* Copy over the sequence table
00222   */
00223   rc = execExecSql(db, 
00224       "SELECT 'DELETE FROM vacuum_db.' || quote(name) || ';' "
00225       "FROM vacuum_db.sqlite_master WHERE name='sqlite_sequence' "
00226   );
00227   if( rc!=SQLITE_OK ) goto end_of_vacuum;
00228   rc = execExecSql(db, 
00229       "SELECT 'INSERT INTO vacuum_db.' || quote(name) "
00230       "|| ' SELECT * FROM ' || quote(name) || ';' "
00231       "FROM vacuum_db.sqlite_master WHERE name=='sqlite_sequence';"
00232   );
00233   if( rc!=SQLITE_OK ) goto end_of_vacuum;
00234 
00235 
00236   /* Copy the triggers from the main database to the temporary database.
00237   ** This was deferred before in case the triggers interfered with copying
00238   ** the data. It's possible the indices should be deferred until this
00239   ** point also.
00240   */
00241   rc = execExecSql(db, 
00242       "SELECT 'CREATE TRIGGER  vacuum_db.' || substr(sql, 16, 1000000) "
00243       "FROM sqlite_master WHERE type='trigger'"
00244   );
00245   if( rc!=SQLITE_OK ) goto end_of_vacuum;
00246 
00247 
00248   /* At this point, unless the main db was completely empty, there is now a
00249   ** transaction open on the vacuum database, but not on the main database.
00250   ** Open a btree level transaction on the main database. This allows a
00251   ** call to sqlite3BtreeCopyFile(). The main database btree level
00252   ** transaction is then committed, so the SQL level never knows it was
00253   ** opened for writing. This way, the SQL transaction used to create the
00254   ** temporary database never needs to be committed.
00255   */
00256   if( rc==SQLITE_OK ){
00257     u32 meta;
00258     int i;
00259 
00260     /* This array determines which meta meta values are preserved in the
00261     ** vacuum.  Even entries are the meta value number and odd entries
00262     ** are an increment to apply to the meta value after the vacuum.
00263     ** The increment is used to increase the schema cookie so that other
00264     ** connections to the same database will know to reread the schema.
00265     */
00266     static const unsigned char aCopy[] = {
00267        1, 1,    /* Add one to the old schema cookie */
00268        3, 0,    /* Preserve the default page cache size */
00269        5, 0,    /* Preserve the default text encoding */
00270        6, 0,    /* Preserve the user version */
00271     };
00272 
00273     assert( 1==sqlite3BtreeIsInTrans(pTemp) );
00274     assert( 1==sqlite3BtreeIsInTrans(pMain) );
00275 
00276     /* Copy Btree meta values */
00277     for(i=0; i<sizeof(aCopy)/sizeof(aCopy[0]); i+=2){
00278       rc = sqlite3BtreeGetMeta(pMain, aCopy[i], &meta);
00279       if( rc!=SQLITE_OK ) goto end_of_vacuum;
00280       rc = sqlite3BtreeUpdateMeta(pTemp, aCopy[i], meta+aCopy[i+1]);
00281       if( rc!=SQLITE_OK ) goto end_of_vacuum;
00282     }
00283 
00284     rc = sqlite3BtreeCopyFile(pMain, pTemp);
00285     if( rc!=SQLITE_OK ) goto end_of_vacuum;
00286     rc = sqlite3BtreeCommit(pTemp);
00287     if( rc!=SQLITE_OK ) goto end_of_vacuum;
00288     rc = sqlite3BtreeCommit(pMain);
00289   }
00290 
00291 end_of_vacuum:
00292   /* Restore the original value of db->flags */
00293   db->flags = saved_flags;
00294 
00295   /* Currently there is an SQL level transaction open on the vacuum
00296   ** database. No locks are held on any other files (since the main file
00297   ** was committed at the btree level). So it safe to end the transaction
00298   ** by manually setting the autoCommit flag to true and detaching the
00299   ** vacuum database. The vacuum_db journal file is deleted when the pager
00300   ** is closed by the DETACH.
00301   */
00302   db->autoCommit = 1;
00303 
00304   if( pDb ){
00305     sqlite3MallocDisallow();
00306     sqlite3BtreeClose(pDb->pBt);
00307     sqlite3MallocAllow();
00308     pDb->pBt = 0;
00309     pDb->pSchema = 0;
00310   }
00311 
00312   /* If one of the execSql() calls above returned SQLITE_NOMEM, then the
00313   ** mallocFailed flag will be clear (because execSql() calls sqlite3_exec()).
00314   ** Fix this so the flag and return code match.
00315   */
00316   if( rc==SQLITE_NOMEM ){
00317     sqlite3MallocFailed();
00318   }
00319 
00320   if( zTemp ){
00321     sqlite3OsDelete(zTemp);
00322     sqliteFree(zTemp);
00323   }
00324   sqliteFree( zSql );
00325   sqlite3ResetInternalSchema(db, 0);
00326 #endif
00327 
00328   return rc;
00329 }