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.83 2008/08/26 21:07:27 drh Exp $ 00018 */ 00019 #include "sqliteInt.h" 00020 #include "vdbeInt.h" 00021 00022 #if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH) 00023 /* 00024 ** Execute zSql on database db. Return an error code. 00025 */ 00026 static int execSql(sqlite3 *db, const char *zSql){ 00027 sqlite3_stmt *pStmt; 00028 if( !zSql ){ 00029 return SQLITE_NOMEM; 00030 } 00031 if( SQLITE_OK!=sqlite3_prepare(db, zSql, -1, &pStmt, 0) ){ 00032 return sqlite3_errcode(db); 00033 } 00034 while( SQLITE_ROW==sqlite3_step(pStmt) ){} 00035 return sqlite3_finalize(pStmt); 00036 } 00037 00038 /* 00039 ** Execute zSql on database db. The statement returns exactly 00040 ** one column. Execute this as SQL on the same database. 00041 */ 00042 static int execExecSql(sqlite3 *db, const char *zSql){ 00043 sqlite3_stmt *pStmt; 00044 int rc; 00045 00046 rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); 00047 if( rc!=SQLITE_OK ) return rc; 00048 00049 while( SQLITE_ROW==sqlite3_step(pStmt) ){ 00050 rc = execSql(db, (char*)sqlite3_column_text(pStmt, 0)); 00051 if( rc!=SQLITE_OK ){ 00052 sqlite3_finalize(pStmt); 00053 return rc; 00054 } 00055 } 00056 00057 return sqlite3_finalize(pStmt); 00058 } 00059 00060 /* 00061 ** The non-standard VACUUM command is used to clean up the database, 00062 ** collapse free space, etc. It is modelled after the VACUUM command 00063 ** in PostgreSQL. 00064 ** 00065 ** In version 1.0.x of SQLite, the VACUUM command would call 00066 ** gdbm_reorganize() on all the database tables. But beginning 00067 ** with 2.0.0, SQLite no longer uses GDBM so this command has 00068 ** become a no-op. 00069 */ 00070 void sqlite3Vacuum(Parse *pParse){ 00071 Vdbe *v = sqlite3GetVdbe(pParse); 00072 if( v ){ 00073 sqlite3VdbeAddOp2(v, OP_Vacuum, 0, 0); 00074 } 00075 return; 00076 } 00077 00078 /* 00079 ** This routine implements the OP_Vacuum opcode of the VDBE. 00080 */ 00081 int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ 00082 int rc = SQLITE_OK; /* Return code from service routines */ 00083 Btree *pMain; /* The database being vacuumed */ 00084 Pager *pMainPager; /* Pager for database being vacuumed */ 00085 Btree *pTemp; /* The temporary database we vacuum into */ 00086 char *zSql = 0; /* SQL statements */ 00087 int saved_flags; /* Saved value of the db->flags */ 00088 int saved_nChange; /* Saved value of db->nChange */ 00089 int saved_nTotalChange; /* Saved value of db->nTotalChange */ 00090 Db *pDb = 0; /* Database to detach at end of vacuum */ 00091 int isMemDb; /* True is vacuuming a :memory: database */ 00092 int nRes; 00093 00094 /* Save the current value of the write-schema flag before setting it. */ 00095 saved_flags = db->flags; 00096 saved_nChange = db->nChange; 00097 saved_nTotalChange = db->nTotalChange; 00098 db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks; 00099 00100 if( !db->autoCommit ){ 00101 sqlite3SetString(pzErrMsg, db, "cannot VACUUM from within a transaction"); 00102 rc = SQLITE_ERROR; 00103 goto end_of_vacuum; 00104 } 00105 pMain = db->aDb[0].pBt; 00106 pMainPager = sqlite3BtreePager(pMain); 00107 isMemDb = sqlite3PagerFile(pMainPager)->pMethods==0; 00108 00109 /* Attach the temporary database as 'vacuum_db'. The synchronous pragma 00110 ** can be set to 'off' for this file, as it is not recovered if a crash 00111 ** occurs anyway. The integrity of the database is maintained by a 00112 ** (possibly synchronous) transaction opened on the main database before 00113 ** sqlite3BtreeCopyFile() is called. 00114 ** 00115 ** An optimisation would be to use a non-journaled pager. 00116 ** (Later:) I tried setting "PRAGMA vacuum_db.journal_mode=OFF" but 00117 ** that actually made the VACUUM run slower. Very little journalling 00118 ** actually occurs when doing a vacuum since the vacuum_db is initially 00119 ** empty. Only the journal header is written. Apparently it takes more 00120 ** time to parse and run the PRAGMA to turn journalling off than it does 00121 ** to write the journal header file. 00122 */ 00123 zSql = "ATTACH '' AS vacuum_db;"; 00124 rc = execSql(db, zSql); 00125 if( rc!=SQLITE_OK ) goto end_of_vacuum; 00126 pDb = &db->aDb[db->nDb-1]; 00127 assert( strcmp(db->aDb[db->nDb-1].zName,"vacuum_db")==0 ); 00128 pTemp = db->aDb[db->nDb-1].pBt; 00129 00130 nRes = sqlite3BtreeGetReserve(pMain); 00131 00132 /* A VACUUM cannot change the pagesize of an encrypted database. */ 00133 #ifdef SQLITE_HAS_CODEC 00134 if( db->nextPagesize ){ 00135 extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*); 00136 int nKey; 00137 char *zKey; 00138 sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey); 00139 if( nKey ) db->nextPagesize = 0; 00140 } 00141 #endif 00142 00143 if( sqlite3BtreeSetPageSize(pTemp, sqlite3BtreeGetPageSize(pMain), nRes) 00144 || (!isMemDb && sqlite3BtreeSetPageSize(pTemp, db->nextPagesize, nRes)) 00145 || db->mallocFailed 00146 ){ 00147 rc = SQLITE_NOMEM; 00148 goto end_of_vacuum; 00149 } 00150 rc = execSql(db, "PRAGMA vacuum_db.synchronous=OFF"); 00151 if( rc!=SQLITE_OK ){ 00152 goto end_of_vacuum; 00153 } 00154 00155 #ifndef SQLITE_OMIT_AUTOVACUUM 00156 sqlite3BtreeSetAutoVacuum(pTemp, db->nextAutovac>=0 ? db->nextAutovac : 00157 sqlite3BtreeGetAutoVacuum(pMain)); 00158 #endif 00159 00160 /* Begin a transaction */ 00161 rc = execSql(db, "BEGIN EXCLUSIVE;"); 00162 if( rc!=SQLITE_OK ) goto end_of_vacuum; 00163 00164 /* Query the schema of the main database. Create a mirror schema 00165 ** in the temporary database. 00166 */ 00167 rc = execExecSql(db, 00168 "SELECT 'CREATE TABLE vacuum_db.' || substr(sql,14) " 00169 " FROM sqlite_master WHERE type='table' AND name!='sqlite_sequence'" 00170 " AND rootpage>0" 00171 ); 00172 if( rc!=SQLITE_OK ) goto end_of_vacuum; 00173 rc = execExecSql(db, 00174 "SELECT 'CREATE INDEX vacuum_db.' || substr(sql,14)" 00175 " FROM sqlite_master WHERE sql LIKE 'CREATE INDEX %' "); 00176 if( rc!=SQLITE_OK ) goto end_of_vacuum; 00177 rc = execExecSql(db, 00178 "SELECT 'CREATE UNIQUE INDEX vacuum_db.' || substr(sql,21) " 00179 " FROM sqlite_master WHERE sql LIKE 'CREATE UNIQUE INDEX %'"); 00180 if( rc!=SQLITE_OK ) goto end_of_vacuum; 00181 00182 /* Loop through the tables in the main database. For each, do 00183 ** an "INSERT INTO vacuum_db.xxx SELECT * FROM xxx;" to copy 00184 ** the contents to the temporary database. 00185 */ 00186 rc = execExecSql(db, 00187 "SELECT 'INSERT INTO vacuum_db.' || quote(name) " 00188 "|| ' SELECT * FROM ' || quote(name) || ';'" 00189 "FROM sqlite_master " 00190 "WHERE type = 'table' AND name!='sqlite_sequence' " 00191 " AND rootpage>0" 00192 00193 ); 00194 if( rc!=SQLITE_OK ) goto end_of_vacuum; 00195 00196 /* Copy over the sequence table 00197 */ 00198 rc = execExecSql(db, 00199 "SELECT 'DELETE FROM vacuum_db.' || quote(name) || ';' " 00200 "FROM vacuum_db.sqlite_master WHERE name='sqlite_sequence' " 00201 ); 00202 if( rc!=SQLITE_OK ) goto end_of_vacuum; 00203 rc = execExecSql(db, 00204 "SELECT 'INSERT INTO vacuum_db.' || quote(name) " 00205 "|| ' SELECT * FROM ' || quote(name) || ';' " 00206 "FROM vacuum_db.sqlite_master WHERE name=='sqlite_sequence';" 00207 ); 00208 if( rc!=SQLITE_OK ) goto end_of_vacuum; 00209 00210 00211 /* Copy the triggers, views, and virtual tables from the main database 00212 ** over to the temporary database. None of these objects has any 00213 ** associated storage, so all we have to do is copy their entries 00214 ** from the SQLITE_MASTER table. 00215 */ 00216 rc = execSql(db, 00217 "INSERT INTO vacuum_db.sqlite_master " 00218 " SELECT type, name, tbl_name, rootpage, sql" 00219 " FROM sqlite_master" 00220 " WHERE type='view' OR type='trigger'" 00221 " OR (type='table' AND rootpage=0)" 00222 ); 00223 if( rc ) goto end_of_vacuum; 00224 00225 /* At this point, unless the main db was completely empty, there is now a 00226 ** transaction open on the vacuum database, but not on the main database. 00227 ** Open a btree level transaction on the main database. This allows a 00228 ** call to sqlite3BtreeCopyFile(). The main database btree level 00229 ** transaction is then committed, so the SQL level never knows it was 00230 ** opened for writing. This way, the SQL transaction used to create the 00231 ** temporary database never needs to be committed. 00232 */ 00233 if( rc==SQLITE_OK ){ 00234 u32 meta; 00235 int i; 00236 00237 /* This array determines which meta meta values are preserved in the 00238 ** vacuum. Even entries are the meta value number and odd entries 00239 ** are an increment to apply to the meta value after the vacuum. 00240 ** The increment is used to increase the schema cookie so that other 00241 ** connections to the same database will know to reread the schema. 00242 */ 00243 static const unsigned char aCopy[] = { 00244 1, 1, /* Add one to the old schema cookie */ 00245 3, 0, /* Preserve the default page cache size */ 00246 5, 0, /* Preserve the default text encoding */ 00247 6, 0, /* Preserve the user version */ 00248 }; 00249 00250 assert( 1==sqlite3BtreeIsInTrans(pTemp) ); 00251 assert( 1==sqlite3BtreeIsInTrans(pMain) ); 00252 00253 /* Copy Btree meta values */ 00254 for(i=0; i<sizeof(aCopy)/sizeof(aCopy[0]); i+=2){ 00255 rc = sqlite3BtreeGetMeta(pMain, aCopy[i], &meta); 00256 if( rc!=SQLITE_OK ) goto end_of_vacuum; 00257 rc = sqlite3BtreeUpdateMeta(pTemp, aCopy[i], meta+aCopy[i+1]); 00258 if( rc!=SQLITE_OK ) goto end_of_vacuum; 00259 } 00260 00261 rc = sqlite3BtreeCopyFile(pMain, pTemp); 00262 if( rc!=SQLITE_OK ) goto end_of_vacuum; 00263 rc = sqlite3BtreeCommit(pTemp); 00264 if( rc!=SQLITE_OK ) goto end_of_vacuum; 00265 #ifndef SQLITE_OMIT_AUTOVACUUM 00266 sqlite3BtreeSetAutoVacuum(pMain, sqlite3BtreeGetAutoVacuum(pTemp)); 00267 #endif 00268 rc = sqlite3BtreeCommit(pMain); 00269 } 00270 00271 if( rc==SQLITE_OK ){ 00272 rc = sqlite3BtreeSetPageSize(pMain, sqlite3BtreeGetPageSize(pTemp), nRes); 00273 } 00274 00275 end_of_vacuum: 00276 /* Restore the original value of db->flags */ 00277 db->flags = saved_flags; 00278 db->nChange = saved_nChange; 00279 db->nTotalChange = saved_nTotalChange; 00280 00281 /* Currently there is an SQL level transaction open on the vacuum 00282 ** database. No locks are held on any other files (since the main file 00283 ** was committed at the btree level). So it safe to end the transaction 00284 ** by manually setting the autoCommit flag to true and detaching the 00285 ** vacuum database. The vacuum_db journal file is deleted when the pager 00286 ** is closed by the DETACH. 00287 */ 00288 db->autoCommit = 1; 00289 00290 if( pDb ){ 00291 sqlite3BtreeClose(pDb->pBt); 00292 pDb->pBt = 0; 00293 pDb->pSchema = 0; 00294 } 00295 00296 sqlite3ResetInternalSchema(db, 0); 00297 00298 return rc; 00299 } 00300 #endif /* SQLITE_OMIT_VACUUM && SQLITE_OMIT_ATTACH */
ContextLogger2—ContextLogger2 Logger Daemon Internals—Generated on Mon May 2 13:49:57 2011 by Doxygen 1.6.1