| OLD | NEW |
| 1 /* | 1 /* |
| 2 ** 2003 April 6 | 2 ** 2003 April 6 |
| 3 ** | 3 ** |
| 4 ** The author disclaims copyright to this source code. In place of | 4 ** The author disclaims copyright to this source code. In place of |
| 5 ** a legal notice, here is a blessing: | 5 ** a legal notice, here is a blessing: |
| 6 ** | 6 ** |
| 7 ** May you do good and not evil. | 7 ** May you do good and not evil. |
| 8 ** May you find forgiveness for yourself and forgive others. | 8 ** May you find forgiveness for yourself and forgive others. |
| 9 ** May you share freely, never taking more than you give. | 9 ** May you share freely, never taking more than you give. |
| 10 ** | 10 ** |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 87 ** step (3) requires additional temporary disk space approximately equal | 87 ** step (3) requires additional temporary disk space approximately equal |
| 88 ** to the size of the original database for the rollback journal. | 88 ** to the size of the original database for the rollback journal. |
| 89 ** Hence, temporary disk space that is approximately 2x the size of the | 89 ** Hence, temporary disk space that is approximately 2x the size of the |
| 90 ** original database is required. Every page of the database is written | 90 ** original database is required. Every page of the database is written |
| 91 ** approximately 3 times: Once for step (2) and twice for step (3). | 91 ** approximately 3 times: Once for step (2) and twice for step (3). |
| 92 ** Two writes per page are required in step (3) because the original | 92 ** Two writes per page are required in step (3) because the original |
| 93 ** database content must be written into the rollback journal prior to | 93 ** database content must be written into the rollback journal prior to |
| 94 ** overwriting the database with the vacuumed content. | 94 ** overwriting the database with the vacuumed content. |
| 95 ** | 95 ** |
| 96 ** Only 1x temporary space and only 1x writes would be required if | 96 ** Only 1x temporary space and only 1x writes would be required if |
| 97 ** the copy of step (3) were replace by deleting the original database | 97 ** the copy of step (3) were replaced by deleting the original database |
| 98 ** and renaming the transient database as the original. But that will | 98 ** and renaming the transient database as the original. But that will |
| 99 ** not work if other processes are attached to the original database. | 99 ** not work if other processes are attached to the original database. |
| 100 ** And a power loss in between deleting the original and renaming the | 100 ** And a power loss in between deleting the original and renaming the |
| 101 ** transient would cause the database file to appear to be deleted | 101 ** transient would cause the database file to appear to be deleted |
| 102 ** following reboot. | 102 ** following reboot. |
| 103 */ | 103 */ |
| 104 void sqlite3Vacuum(Parse *pParse){ | 104 void sqlite3Vacuum(Parse *pParse){ |
| 105 Vdbe *v = sqlite3GetVdbe(pParse); | 105 Vdbe *v = sqlite3GetVdbe(pParse); |
| 106 if( v ){ | 106 if( v ){ |
| 107 sqlite3VdbeAddOp2(v, OP_Vacuum, 0, 0); | 107 sqlite3VdbeAddOp2(v, OP_Vacuum, 0, 0); |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 177 } | 177 } |
| 178 if( rc!=SQLITE_OK ) goto end_of_vacuum; | 178 if( rc!=SQLITE_OK ) goto end_of_vacuum; |
| 179 pTemp = db->aDb[db->nDb-1].pBt; | 179 pTemp = db->aDb[db->nDb-1].pBt; |
| 180 | 180 |
| 181 /* The call to execSql() to attach the temp database has left the file | 181 /* The call to execSql() to attach the temp database has left the file |
| 182 ** locked (as there was more than one active statement when the transaction | 182 ** locked (as there was more than one active statement when the transaction |
| 183 ** to read the schema was concluded. Unlock it here so that this doesn't | 183 ** to read the schema was concluded. Unlock it here so that this doesn't |
| 184 ** cause problems for the call to BtreeSetPageSize() below. */ | 184 ** cause problems for the call to BtreeSetPageSize() below. */ |
| 185 sqlite3BtreeCommit(pTemp); | 185 sqlite3BtreeCommit(pTemp); |
| 186 | 186 |
| 187 nRes = sqlite3BtreeGetReserve(pMain); | 187 nRes = sqlite3BtreeGetOptimalReserve(pMain); |
| 188 | 188 |
| 189 /* A VACUUM cannot change the pagesize of an encrypted database. */ | 189 /* A VACUUM cannot change the pagesize of an encrypted database. */ |
| 190 #ifdef SQLITE_HAS_CODEC | 190 #ifdef SQLITE_HAS_CODEC |
| 191 if( db->nextPagesize ){ | 191 if( db->nextPagesize ){ |
| 192 extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*); | 192 extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*); |
| 193 int nKey; | 193 int nKey; |
| 194 char *zKey; | 194 char *zKey; |
| 195 sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey); | 195 sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey); |
| 196 if( nKey ) db->nextPagesize = 0; | 196 if( nKey ) db->nextPagesize = 0; |
| 197 } | 197 } |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 243 if( rc!=SQLITE_OK ) goto end_of_vacuum; | 243 if( rc!=SQLITE_OK ) goto end_of_vacuum; |
| 244 rc = execExecSql(db, pzErrMsg, | 244 rc = execExecSql(db, pzErrMsg, |
| 245 "SELECT 'CREATE UNIQUE INDEX vacuum_db.' || substr(sql,21) " | 245 "SELECT 'CREATE UNIQUE INDEX vacuum_db.' || substr(sql,21) " |
| 246 " FROM sqlite_master WHERE sql LIKE 'CREATE UNIQUE INDEX %'"); | 246 " FROM sqlite_master WHERE sql LIKE 'CREATE UNIQUE INDEX %'"); |
| 247 if( rc!=SQLITE_OK ) goto end_of_vacuum; | 247 if( rc!=SQLITE_OK ) goto end_of_vacuum; |
| 248 | 248 |
| 249 /* Loop through the tables in the main database. For each, do | 249 /* Loop through the tables in the main database. For each, do |
| 250 ** an "INSERT INTO vacuum_db.xxx SELECT * FROM main.xxx;" to copy | 250 ** an "INSERT INTO vacuum_db.xxx SELECT * FROM main.xxx;" to copy |
| 251 ** the contents to the temporary database. | 251 ** the contents to the temporary database. |
| 252 */ | 252 */ |
| 253 assert( (db->flags & SQLITE_Vacuum)==0 ); |
| 254 db->flags |= SQLITE_Vacuum; |
| 253 rc = execExecSql(db, pzErrMsg, | 255 rc = execExecSql(db, pzErrMsg, |
| 254 "SELECT 'INSERT INTO vacuum_db.' || quote(name) " | 256 "SELECT 'INSERT INTO vacuum_db.' || quote(name) " |
| 255 "|| ' SELECT * FROM main.' || quote(name) || ';'" | 257 "|| ' SELECT * FROM main.' || quote(name) || ';'" |
| 256 "FROM main.sqlite_master " | 258 "FROM main.sqlite_master " |
| 257 "WHERE type = 'table' AND name!='sqlite_sequence' " | 259 "WHERE type = 'table' AND name!='sqlite_sequence' " |
| 258 " AND coalesce(rootpage,1)>0" | 260 " AND coalesce(rootpage,1)>0" |
| 259 ); | 261 ); |
| 262 assert( (db->flags & SQLITE_Vacuum)!=0 ); |
| 263 db->flags &= ~SQLITE_Vacuum; |
| 260 if( rc!=SQLITE_OK ) goto end_of_vacuum; | 264 if( rc!=SQLITE_OK ) goto end_of_vacuum; |
| 261 | 265 |
| 262 /* Copy over the sequence table | 266 /* Copy over the sequence table |
| 263 */ | 267 */ |
| 264 rc = execExecSql(db, pzErrMsg, | 268 rc = execExecSql(db, pzErrMsg, |
| 265 "SELECT 'DELETE FROM vacuum_db.' || quote(name) || ';' " | 269 "SELECT 'DELETE FROM vacuum_db.' || quote(name) || ';' " |
| 266 "FROM vacuum_db.sqlite_master WHERE name='sqlite_sequence' " | 270 "FROM vacuum_db.sqlite_master WHERE name='sqlite_sequence' " |
| 267 ); | 271 ); |
| 268 if( rc!=SQLITE_OK ) goto end_of_vacuum; | 272 if( rc!=SQLITE_OK ) goto end_of_vacuum; |
| 269 rc = execExecSql(db, pzErrMsg, | 273 rc = execExecSql(db, pzErrMsg, |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 360 } | 364 } |
| 361 | 365 |
| 362 /* This both clears the schemas and reduces the size of the db->aDb[] | 366 /* This both clears the schemas and reduces the size of the db->aDb[] |
| 363 ** array. */ | 367 ** array. */ |
| 364 sqlite3ResetAllSchemasOfConnection(db); | 368 sqlite3ResetAllSchemasOfConnection(db); |
| 365 | 369 |
| 366 return rc; | 370 return rc; |
| 367 } | 371 } |
| 368 | 372 |
| 369 #endif /* SQLITE_OMIT_VACUUM && SQLITE_OMIT_ATTACH */ | 373 #endif /* SQLITE_OMIT_VACUUM && SQLITE_OMIT_ATTACH */ |
| OLD | NEW |