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 |