Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Make VACUUM work even if multiple processes have the database open at once. (CVS 933) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
caa960289f3d1f5e8f35a94e9e432199 |
User & Date: | drh 2003-04-25 13:22:52.000 |
Context
2003-04-25
| ||
13:28 | Work around a name collision problem on windows. (CVS 934) (check-in: c3b1f84dfc user: drh tags: trunk) | |
13:22 | Make VACUUM work even if multiple processes have the database open at once. (CVS 933) (check-in: caa960289f user: drh tags: trunk) | |
03:13 | Explicit casts to squelch bogus warnings for vc++. Ticket #194. (CVS 932) (check-in: cb808c14bc user: drh tags: trunk) | |
Changes
Changes to src/btree.c.
1 2 3 4 5 6 7 8 9 10 11 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** $Id: btree.c,v 1.91 2003/04/25 13:22:52 drh Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to ** ** Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3: ** "Sorting And Searching", pages 473-480. Addison-Wesley ** Publishing Company, Reading, Massachusetts. |
︙ | ︙ | |||
3486 3487 3488 3489 3490 3491 3492 | */ static const char *fileBtreeGetFilename(Btree *pBt){ assert( pBt->pPager!=0 ); return sqlitepager_filename(pBt->pPager); } /* | | > > > > | > > > > > > > > > > > > > > > > > > > > | | 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 | */ static const char *fileBtreeGetFilename(Btree *pBt){ assert( pBt->pPager!=0 ); return sqlitepager_filename(pBt->pPager); } /* ** Copy the complete content of pBtFrom into pBtTo. A transaction ** must be active for both files. ** ** The size of file pBtFrom may be reduced by this operation. ** If anything goes wrong, the transaction on pBtFrom is rolled back. */ static int fileBtreeCopyFile(Btree *pBtTo, Btree *pBtFrom){ int rc = SQLITE_OK; Pgno i, nPage; if( !pBtTo->inTrans || !pBtFrom->inTrans ) return SQLITE_ERROR; if( pBtTo->needSwab!=pBtFrom->needSwab ) return SQLITE_ERROR; if( pBtTo->pCursor ) return SQLITE_BUSY; memcpy(pBtTo->page1, pBtFrom->page1, SQLITE_PAGE_SIZE); sqlitepager_overwrite(pBtTo->pPager, 1, pBtFrom->page1); nPage = sqlitepager_pagecount(pBtFrom->pPager); for(i=2; i<=nPage; i++){ void *pPage; rc = sqlitepager_get(pBtFrom->pPager, i, &pPage); if( rc ) break; sqlitepager_overwrite(pBtTo->pPager, i, pPage); sqlitepager_unref(pPage); } if( !rc ) rc = sqlitepager_truncate(pBtTo->pPager, nPage); if( rc ){ fileBtreeRollback(pBtTo); } return rc; } /* ** The following tables contain pointers to all of the interface ** routines for this implementation of the B*Tree backend. To ** substitute a different implemention of the backend, one has merely ** to provide pointers to alternative functions in similar tables. |
︙ | ︙ | |||
3517 3518 3519 3520 3521 3522 3523 | fileBtreeDropTable, fileBtreeClearTable, fileBtreeCursor, fileBtreeGetMeta, fileBtreeUpdateMeta, fileBtreeIntegrityCheck, fileBtreeGetFilename, | | | 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 | fileBtreeDropTable, fileBtreeClearTable, fileBtreeCursor, fileBtreeGetMeta, fileBtreeUpdateMeta, fileBtreeIntegrityCheck, fileBtreeGetFilename, fileBtreeCopyFile, #ifdef SQLITE_TEST fileBtreePageDump, fileBtreePager #endif }; static BtCursorOps sqliteBtreeCursorOps = { fileBtreeMoveto, |
︙ | ︙ |
Changes to src/btree.h.
︙ | ︙ | |||
9 10 11 12 13 14 15 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** This header file defines the interface that the sqlite B-Tree file ** subsystem. See comments in the source code for a detailed description ** of what each interface routine does. ** | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** This header file defines the interface that the sqlite B-Tree file ** subsystem. See comments in the source code for a detailed description ** of what each interface routine does. ** ** @(#) $Id: btree.h,v 1.33 2003/04/25 13:22:53 drh Exp $ */ #ifndef _BTREE_H_ #define _BTREE_H_ /* ** Forward declarations of structure */ |
︙ | ︙ | |||
52 53 54 55 56 57 58 | int (*DropTable)(Btree*, int); int (*ClearTable)(Btree*, int); int (*Cursor)(Btree*, int iTable, int wrFlag, BtCursor **ppCur); int (*GetMeta)(Btree*, int*); int (*UpdateMeta)(Btree*, int*); char *(*IntegrityCheck)(Btree*, int*, int); const char *(*GetFilename)(Btree*); | | | 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | int (*DropTable)(Btree*, int); int (*ClearTable)(Btree*, int); int (*Cursor)(Btree*, int iTable, int wrFlag, BtCursor **ppCur); int (*GetMeta)(Btree*, int*); int (*UpdateMeta)(Btree*, int*); char *(*IntegrityCheck)(Btree*, int*, int); const char *(*GetFilename)(Btree*); int (*CopyFile)(Btree*,Btree*); #ifdef SQLITE_TEST int (*PageDump)(Btree*, int, int); struct Pager *(*Pager)(Btree*); #endif }; /* |
︙ | ︙ | |||
137 138 139 140 141 142 143 | (btCOps(pCur)->Data(pCur, offset, amt, zBuf)) #define sqliteBtreeCloseCursor(pCur) (btCOps(pCur)->CloseCursor(pCur)) #define sqliteBtreeGetMeta(pBt, aMeta) (btOps(pBt)->GetMeta(pBt, aMeta)) #define sqliteBtreeUpdateMeta(pBt, aMeta) (btOps(pBt)->UpdateMeta(pBt, aMeta)) #define sqliteBtreeIntegrityCheck(pBt, aRoot, nRoot)\ (btOps(pBt)->IntegrityCheck(pBt, aRoot, nRoot)) #define sqliteBtreeGetFilename(pBt) (btOps(pBt)->GetFilename(pBt)) | | < | 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 | (btCOps(pCur)->Data(pCur, offset, amt, zBuf)) #define sqliteBtreeCloseCursor(pCur) (btCOps(pCur)->CloseCursor(pCur)) #define sqliteBtreeGetMeta(pBt, aMeta) (btOps(pBt)->GetMeta(pBt, aMeta)) #define sqliteBtreeUpdateMeta(pBt, aMeta) (btOps(pBt)->UpdateMeta(pBt, aMeta)) #define sqliteBtreeIntegrityCheck(pBt, aRoot, nRoot)\ (btOps(pBt)->IntegrityCheck(pBt, aRoot, nRoot)) #define sqliteBtreeGetFilename(pBt) (btOps(pBt)->GetFilename(pBt)) #define sqliteBtreeCopyFile(pBt1, pBt2) (btOps(pBt1)->CopyFile(pBt1, pBt2)) #ifdef SQLITE_TEST #define sqliteBtreePageDump(pBt, pgno, recursive)\ (btOps(pBt)->PageDump(pBt, pgno, recursive)) #define sqliteBtreeCursorDump(pCur, aResult)\ (btCOps(pCur)->CursorDump(pCur, aResult)) #define sqliteBtreePager(pBt) (btOps(pBt)->Pager(pBt)) int btree_native_byte_order; #endif /* SQLITE_TEST */ #endif /* _BTREE_H_ */ |
Changes to src/btree_rb.c.
1 2 3 4 5 6 7 8 9 10 11 | /* ** 2003 Feb 4 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /* ** 2003 Feb 4 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** $Id: btree_rb.c,v 1.9 2003/04/25 13:22:53 drh Exp $ ** ** This file implements an in-core database using Red-Black balanced ** binary trees. ** ** It was contributed to SQLite by anonymous on 2003-Feb-04 23:24:49 UTC. */ #include "btree.h" |
︙ | ︙ | |||
1327 1328 1329 1330 1331 1332 1333 | ** Return the full pathname of the underlying database file. */ static const char *memBtreeGetFilename(Btree *pBt){ return 0; /* A NULL return indicates there is no underlying file */ } /* | | | | | 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 | ** Return the full pathname of the underlying database file. */ static const char *memBtreeGetFilename(Btree *pBt){ return 0; /* A NULL return indicates there is no underlying file */ } /* ** The copy file function is not implemented for the in-memory database */ static int memBtreeCopyFile(Btree *pBt, Btree *pBt2){ return SQLITE_INTERNAL; /* Not implemented */ } static BtOps sqliteBtreeOps = { memBtreeClose, memBtreeSetCacheSize, memBtreeSetSafetyLevel, memBtreeBeginTrans, |
︙ | ︙ | |||
1352 1353 1354 1355 1356 1357 1358 | memBtreeDropTable, memBtreeClearTable, memBtreeCursor, memBtreeGetMeta, memBtreeUpdateMeta, memBtreeIntegrityCheck, memBtreeGetFilename, | | | 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 | memBtreeDropTable, memBtreeClearTable, memBtreeCursor, memBtreeGetMeta, memBtreeUpdateMeta, memBtreeIntegrityCheck, memBtreeGetFilename, memBtreeCopyFile, #ifdef SQLITE_TEST memBtreePageDump, memBtreePager #endif }; |
︙ | ︙ |
Changes to src/os.c.
︙ | ︙ | |||
278 279 280 281 282 283 284 285 286 287 288 289 290 291 | #endif #if OS_MAC return access(zFilename, 0)==0; #endif } /* ** Change the name of an existing file. */ int sqliteOsFileRename(const char *zOldName, const char *zNewName){ #if OS_UNIX if( link(zOldName, zNewName) ){ return SQLITE_ERROR; | > | 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 | #endif #if OS_MAC return access(zFilename, 0)==0; #endif } #if 0 /* NOT USED */ /* ** Change the name of an existing file. */ int sqliteOsFileRename(const char *zOldName, const char *zNewName){ #if OS_UNIX if( link(zOldName, zNewName) ){ return SQLITE_ERROR; |
︙ | ︙ | |||
300 301 302 303 304 305 306 | return SQLITE_OK; #endif #if OS_MAC /**** FIX ME ***/ return SQLITE_ERROR; #endif } | | | 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 | return SQLITE_OK; #endif #if OS_MAC /**** FIX ME ***/ return SQLITE_ERROR; #endif } #endif /* NOT USED */ /* ** Attempt to open a file for both reading and writing. If that ** fails, try opening it read-only. If the file does not exist, ** try to create it. ** ** On success, a handle for the open file is written to *id |
︙ | ︙ |
Changes to src/pager.c.
︙ | ︙ | |||
14 15 16 17 18 19 20 | ** The pager is used to access a database disk file. It implements ** atomic commit and rollback through the use of a journal file that ** is separate from the database file. The pager also implements file ** locking to prevent two processes from writing the same database ** file simultaneously, or one process from reading the database while ** another is writing. ** | | | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | ** The pager is used to access a database disk file. It implements ** atomic commit and rollback through the use of a journal file that ** is separate from the database file. The pager also implements file ** locking to prevent two processes from writing the same database ** file simultaneously, or one process from reading the database while ** another is writing. ** ** @(#) $Id: pager.c,v 1.82 2003/04/25 13:22:53 drh Exp $ */ #include "os.h" /* Must be first to enable large file support */ #include "sqliteInt.h" #include "pager.h" #include <assert.h> #include <string.h> |
︙ | ︙ | |||
922 923 924 925 926 927 928 929 930 931 932 933 934 935 | } n /= SQLITE_PAGE_SIZE; if( pPager->state!=SQLITE_UNLOCK ){ pPager->dbSize = n; } return n; } /* ** Shutdown the page cache. Free all memory and close all files. ** ** If a transaction was in progress when this routine is called, that ** transaction is rolled back. All outstanding pages are invalidated ** and their memory is freed. Any attempt to use a page associated | > > > > > > > > > > > > > > > > > > > > > > | 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 | } n /= SQLITE_PAGE_SIZE; if( pPager->state!=SQLITE_UNLOCK ){ pPager->dbSize = n; } return n; } /* ** Forward declaration */ static int syncAllPages(Pager*); /* ** Truncate the file to the number of pages specified. */ int sqlitepager_truncate(Pager *pPager, Pgno nPage){ int rc; if( pPager->dbSize<0 ) sqlitepager_pagecount(pPager); if( nPage>=pPager->dbSize ){ return SQLITE_OK; } syncAllPages(pPager); rc = sqliteOsTruncate(&pPager->fd, SQLITE_PAGE_SIZE*(off_t)nPage); if( rc==SQLITE_OK ){ pPager->dbSize = nPage; } return rc; } /* ** Shutdown the page cache. Free all memory and close all files. ** ** If a transaction was in progress when this routine is called, that ** transaction is rolled back. All outstanding pages are invalidated ** and their memory is freed. Any attempt to use a page associated |
︙ | ︙ | |||
2033 2034 2035 2036 2037 2038 2039 | /* ** Return the full pathname of the database file. */ const char *sqlitepager_filename(Pager *pPager){ return pPager->zFilename; } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 | /* ** Return the full pathname of the database file. */ const char *sqlitepager_filename(Pager *pPager){ return pPager->zFilename; } #ifdef SQLITE_TEST /* ** Print a listing of all referenced pages and their ref count. */ void sqlitepager_refdump(Pager *pPager){ PgHdr *pPg; for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ if( pPg->nRef<=0 ) continue; printf("PAGE %3d addr=0x%08x nRef=%d\n", pPg->pgno, (int)PGHDR_TO_DATA(pPg), pPg->nRef); } } #endif |
Changes to src/pager.h.
︙ | ︙ | |||
9 10 11 12 13 14 15 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** This header file defines the interface that the sqlite page cache ** subsystem. The page cache subsystem reads and writes a file a page ** at a time and provides a journal for rollback. ** | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** This header file defines the interface that the sqlite page cache ** subsystem. The page cache subsystem reads and writes a file a page ** at a time and provides a journal for rollback. ** ** @(#) $Id: pager.h,v 1.23 2003/04/25 13:22:53 drh Exp $ */ /* ** The size of one page ** ** You can change this value to another (reasonable) power of two ** such as 512, 2048, 4096, or 8192 and things will still work. But |
︙ | ︙ | |||
57 58 59 60 61 62 63 64 65 66 67 68 69 70 | int sqlitepager_ref(void*); int sqlitepager_unref(void*); Pgno sqlitepager_pagenumber(void*); int sqlitepager_write(void*); int sqlitepager_iswriteable(void*); int sqlitepager_overwrite(Pager *pPager, Pgno pgno, void*); int sqlitepager_pagecount(Pager*); int sqlitepager_begin(void*); int sqlitepager_commit(Pager*); int sqlitepager_rollback(Pager*); int sqlitepager_isreadonly(Pager*); int sqlitepager_ckpt_begin(Pager*); int sqlitepager_ckpt_commit(Pager*); int sqlitepager_ckpt_rollback(Pager*); | > | 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | int sqlitepager_ref(void*); int sqlitepager_unref(void*); Pgno sqlitepager_pagenumber(void*); int sqlitepager_write(void*); int sqlitepager_iswriteable(void*); int sqlitepager_overwrite(Pager *pPager, Pgno pgno, void*); int sqlitepager_pagecount(Pager*); int sqlitepager_truncate(Pager*,Pgno); int sqlitepager_begin(void*); int sqlitepager_commit(Pager*); int sqlitepager_rollback(Pager*); int sqlitepager_isreadonly(Pager*); int sqlitepager_ckpt_begin(Pager*); int sqlitepager_ckpt_commit(Pager*); int sqlitepager_ckpt_rollback(Pager*); |
︙ | ︙ |
Changes to src/vacuum.c.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** This file contains code used to implement the VACUUM command. ** ** Most of the code in this file may be omitted by defining the ** SQLITE_OMIT_VACUUM macro. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** This file contains code used to implement the VACUUM command. ** ** Most of the code in this file may be omitted by defining the ** SQLITE_OMIT_VACUUM macro. ** ** $Id: vacuum.c,v 1.5 2003/04/25 13:22:53 drh Exp $ */ #include "sqliteInt.h" #include "os.h" #define SQLITE_OMIT_VACUUM 1 /* |
︙ | ︙ | |||
205 206 207 208 209 210 211 | ** become a no-op. */ void sqliteVacuum(Parse *pParse, Token *pTableName){ #ifdef SQLITE_OMIT_VACUUM const char *zFilename; /* full pathname of the database file */ int nFilename; /* number of characters in zFilename[] */ char *zTemp = 0; /* a temporary file in same directory as zFilename */ | < | > | < | | | 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 | ** become a no-op. */ void sqliteVacuum(Parse *pParse, Token *pTableName){ #ifdef SQLITE_OMIT_VACUUM const char *zFilename; /* full pathname of the database file */ int nFilename; /* number of characters in zFilename[] */ char *zTemp = 0; /* a temporary file in same directory as zFilename */ sqlite *dbNew = 0; /* The new vacuumed database */ sqlite *db; /* The original database */ int rc = SQLITE_OK; /* Return code from service routines */ int i; /* Loop counter */ char *zErrMsg = 0; /* Error messages stored here */ int safety = 0; /* TRUE if safety is off */ vacuumStruct sVac; /* Information passed to callbacks */ /* These are all of the pragmas that need to be transferred over ** to the new database */ static const char *zPragma[] = { "default_synchronous", "default_cache_size", /* "default_temp_store", */ |
︙ | ︙ | |||
244 245 246 247 248 249 250 | zFilename = sqliteBtreeGetFilename(db->aDb[0].pBt); if( zFilename==0 ){ /* This only happens with the in-memory database. VACUUM is a no-op ** there, so just return */ return; } nFilename = strlen(zFilename); | | < < < < | | > | > > | | < | | | < < < < | < | < < < < < < < < < | < | < < | < < < < < | 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 | zFilename = sqliteBtreeGetFilename(db->aDb[0].pBt); if( zFilename==0 ){ /* This only happens with the in-memory database. VACUUM is a no-op ** there, so just return */ return; } nFilename = strlen(zFilename); zTemp = sqliteMalloc( nFilename+100 ); if( zTemp==0 ) return; strcpy(zTemp, zFilename); for(i=0; i<10; i++){ zTemp[nFilename] = '-'; randomName(&zTemp[nFilename+1]); if( !sqliteOsFileExists(zTemp) ) break; } if( i>=10 ){ sqliteErrorMsg(pParse, "unable to create a temporary database file " "in the same directory as the original database"); goto end_of_vacuum; } dbNew = sqlite_open(zTemp, 0, &zErrMsg); if( dbNew==0 ){ sqliteErrorMsg(pParse, "unable to open a temporary database at %s - %s", zTemp, zErrMsg); goto end_of_vacuum; } if( sqliteSafetyOff(db) ){ sqliteErrorMsg(pParse, "library routines called out of sequence"); goto end_of_vacuum; } safety = 1; if( execsql(pParse, db, "BEGIN") ) goto end_of_vacuum; if( execsql(pParse, dbNew, "PRAGMA synchronous=off; BEGIN") ){ goto end_of_vacuum; } sVac.dbOld = db; sVac.dbNew = dbNew; sVac.pParse = pParse; for(i=0; i<sizeof(zPragma)/sizeof(zPragma[0]); i++){ char zBuf[200]; assert( strlen(zPragma[i])<100 ); sprintf(zBuf, "PRAGMA %s;", zPragma[i]); sVac.zPragma = zPragma[i]; rc = sqlite_exec(db, zBuf, vacuumCallback3, &sVac, &zErrMsg); if( rc ) goto vacuum_error; } if( rc==SQLITE_OK ){ rc = sqlite_exec(db, "SELECT type, name, sql FROM sqlite_master " "WHERE sql NOT NULL", vacuumCallback1, &sVac, &zErrMsg); } if( rc ){ if( pParse->zErrMsg==0 ){ sqliteErrorMsg(pParse, "unable to vacuum database - %s", zErrMsg); } goto end_of_vacuum; } rc = sqliteBtreeCopyFile(db->aDb[0].pBt, dbNew->aDb[0].pBt); sqlite_exec(db, "COMMIT", 0, 0, 0); sqliteResetInternalSchema(db, 0); end_of_vacuum: sqlite_exec(db, "COMMIT", 0, 0, 0); if( safety ) { sqliteSafetyOn(db); } if( dbNew ) sqlite_close(dbNew); sqliteOsDelete(zTemp); sqliteFree(zTemp); sqliteFree(sVac.s1.z); sqliteFree(sVac.s2.z); if( zErrMsg ) sqlite_freemem(zErrMsg); return; vacuum_error: #endif } |
Changes to test/vacuum.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 2001 September 15 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing the VACUUM statement. # | | | | | | | < < < | > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | # 2001 September 15 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing the VACUUM statement. # # $Id: vacuum.test,v 1.9 2003/04/25 13:22:53 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl proc cksum {{db db}} { set txt [$db eval {SELECT name, type, sql FROM sqlite_master}]\n foreach tbl [$db eval {SELECT name FROM sqlite_master WHERE type='table'}] { append txt [$db eval "SELECT * FROM $tbl"]\n } foreach prag {default_synchronous default_cache_size} { append txt $prag-[$db eval "PRAGMA $prag"]\n } set cksum [string length $txt]-[md5 $txt] puts $cksum-[file size test.db] return $cksum } do_test vacuum-1.1 { execsql { BEGIN; CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); INSERT INTO t1 VALUES(NULL,randstr(10,100),randstr(5,50)); |
︙ | ︙ | |||
45 46 47 48 49 50 51 | INSERT INTO t1 SELECT NULL, b||'-'||rowid, c||'-'||rowid FROM t1; CREATE INDEX i1 ON t1(b,c); CREATE TABLE t2 AS SELECT * FROM t1; COMMIT; DROP TABLE t2; } set ::size1 [file size test.db] | | | | | > > > | > > > > > > > > > > | > > > > > > > > > > > > > > > | 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | INSERT INTO t1 SELECT NULL, b||'-'||rowid, c||'-'||rowid FROM t1; CREATE INDEX i1 ON t1(b,c); CREATE TABLE t2 AS SELECT * FROM t1; COMMIT; DROP TABLE t2; } set ::size1 [file size test.db] set ::cksum [cksum] expr {$::cksum!=""} } {1} do_test vacuum-1.2 { execsql { VACUUM; } cksum } $cksum do_test vacuum-1.3 { expr {[file size test.db]<$::size1} } {1} do_test vacuum-1.4 { execsql { BEGIN; CREATE TABLE t2 AS SELECT * FROM t1; CREATE TABLE t3 AS SELECT * FROM t1; CREATE VIEW v1 AS SELECT b, c FROM t3; CREATE TRIGGER r1 AFTER DELETE ON t2 BEGIN SELECT 1; END; COMMIT; DROP TABLE t2; } set ::size1 [file size test.db] set ::cksum [cksum] expr {$::cksum!=""} } {1} do_test vacuum-1.5 { execsql { VACUUM; } cksum } $cksum do_test vacuum-1.6 { expr {[file size test.db]<$::size1} } {1} do_test vacuum-2.1 { catchsql { BEGIN; VACUUM; COMMIT; } } {1 {cannot VACUUM from within a transaction}} catch {db eval COMMIT} do_test vacuum-2.2 { sqlite db2 test.db execsql { BEGIN; CREATE TABLE t4 AS SELECT * FROM t1; CREATE TABLE t5 AS SELECT * FROM t1; COMMIT; DROP TABLE t4; DROP TABLE t5; } db2 set ::cksum [cksum db2] catchsql { VACUUM } } {1 {database schema has changed}} do_test vacuum-2.3 { execsql { VACUUM; } cksum } $cksum do_test vacuum-2.4 { catch {db2 eval {SELECT count(*) FROM sqlite_master}} cksum db2 } $cksum catch {db2 close} # finish_test |