diff options
author | drh <drh@noemail.net> | 2005-11-04 22:03:30 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2005-11-04 22:03:30 +0000 |
commit | c9ac5caa457b8115bc64212af8ad8323a65d6d5c (patch) | |
tree | cccf1f62c7176c5bb508b7840be4249ddee60a5d /src | |
parent | c01be744bc8e19fa9d74375eba2aab345b296210 (diff) | |
download | sqlite-c9ac5caa457b8115bc64212af8ad8323a65d6d5c.tar.gz sqlite-c9ac5caa457b8115bc64212af8ad8323a65d6d5c.zip |
VACUUM works even on an empty database. Ticket #1512. (CVS 2760)
FossilOrigin-Name: 1b6bf4188e8ebf55cf1972b7081f6d31bf525555
Diffstat (limited to 'src')
-rw-r--r-- | src/os_common.h | 3 | ||||
-rw-r--r-- | src/pager.c | 42 | ||||
-rw-r--r-- | src/test2.c | 5 | ||||
-rw-r--r-- | src/vacuum.c | 22 |
4 files changed, 51 insertions, 21 deletions
diff --git a/src/os_common.h b/src/os_common.h index b19ff0590..112fbb779 100644 --- a/src/os_common.h +++ b/src/os_common.h @@ -88,6 +88,7 @@ static unsigned int elapse; ** is used for testing the I/O recovery logic. */ #ifdef SQLITE_TEST +int sqlite3_io_error_hit = 0; int sqlite3_io_error_pending = 0; int sqlite3_diskfull_pending = 0; int sqlite3_diskfull = 0; @@ -95,7 +96,7 @@ int sqlite3_diskfull = 0; if( sqlite3_io_error_pending ) \ if( sqlite3_io_error_pending-- == 1 ){ local_ioerr(); return A; } static void local_ioerr(){ - sqlite3_io_error_pending = 0; /* Really just a place to set a breakpoint */ + sqlite3_io_error_hit = 1; /* Really just a place to set a breakpoint */ } #define SimulateDiskfullError \ if( sqlite3_diskfull_pending ){ \ diff --git a/src/pager.c b/src/pager.c index 74b55aa1c..cc91672c6 100644 --- a/src/pager.c +++ b/src/pager.c @@ -18,7 +18,7 @@ ** file simultaneously, or one process from reading the database while ** another is writing. ** -** @(#) $Id: pager.c,v 1.215 2005/09/17 15:20:27 drh Exp $ +** @(#) $Id: pager.c,v 1.216 2005/11/04 22:03:30 drh Exp $ */ #ifndef SQLITE_OMIT_DISKIO #include "sqliteInt.h" @@ -1739,6 +1739,34 @@ int sqlite3pager_set_pagesize(Pager *pPager, int pageSize){ } /* +** The following set of routines are used to disable the simulated +** I/O error mechanism. These routines are used to avoid simulated +** errors in places where we do not care about errors. +** +** Unless -DSQLITE_TEST=1 is used, these routines are all no-ops +** and generate no code. +*/ +#ifdef SQLITE_TEST +extern int sqlite3_io_error_pending; +extern int sqlite3_io_error_hit; +static int saved_cnt; +void clear_simulated_io_error(){ + sqlite3_io_error_hit = 0; +} +void disable_simulated_io_errors(void){ + saved_cnt = sqlite3_io_error_pending; + sqlite3_io_error_pending = -1; +} +void enable_simulated_io_errors(void){ + sqlite3_io_error_pending = saved_cnt; +} +#else +# define clear_simulated_io_error(X) +# define disable_simulated_io_errors(X) +# define enable_simulated_io_errors(X) +#endif + +/* ** Read the first N bytes from the beginning of the file into memory ** that pDest points to. No error checking is done. */ @@ -1747,6 +1775,7 @@ void sqlite3pager_read_fileheader(Pager *pPager, int N, unsigned char *pDest){ if( MEMDB==0 ){ sqlite3OsSeek(&pPager->fd, 0); sqlite3OsRead(&pPager->fd, pDest, N); + clear_simulated_io_error(); } } @@ -1961,15 +1990,9 @@ int sqlite3pager_close(Pager *pPager){ ** operation. So disable IO error simulation so that testing ** works more easily. */ -#if defined(SQLITE_TEST) && (defined(OS_UNIX) || defined(OS_WIN)) - extern int sqlite3_io_error_pending; - int ioerr_cnt = sqlite3_io_error_pending; - sqlite3_io_error_pending = -1; -#endif + disable_simulated_io_errors(); sqlite3pager_rollback(pPager); -#if defined(SQLITE_TEST) && (defined(OS_UNIX) || defined(OS_WIN)) - sqlite3_io_error_pending = ioerr_cnt; -#endif + enable_simulated_io_errors(); if( !MEMDB ){ sqlite3OsUnlock(&pPager->fd, NO_LOCK); } @@ -2535,6 +2558,7 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){ sqlite3pager_unref(PGHDR_TO_DATA(pPg)); return rc; }else{ + clear_simulated_io_error(); memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize); } }else{ diff --git a/src/test2.c b/src/test2.c index fa4cd329c..1867fc866 100644 --- a/src/test2.c +++ b/src/test2.c @@ -13,7 +13,7 @@ ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** -** $Id: test2.c,v 1.34 2005/09/16 10:13:42 danielk1977 Exp $ +** $Id: test2.c,v 1.35 2005/11/04 22:03:30 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -560,6 +560,7 @@ static int fake_big_file( */ int Sqlitetest2_Init(Tcl_Interp *interp){ extern int sqlite3_io_error_pending; + extern int sqlite3_io_error_hit; extern int sqlite3_diskfull_pending; extern int sqlite3_diskfull; static struct { @@ -592,6 +593,8 @@ int Sqlitetest2_Init(Tcl_Interp *interp){ } Tcl_LinkVar(interp, "sqlite_io_error_pending", (char*)&sqlite3_io_error_pending, TCL_LINK_INT); + Tcl_LinkVar(interp, "sqlite_io_error_hit", + (char*)&sqlite3_io_error_hit, TCL_LINK_INT); Tcl_LinkVar(interp, "sqlite_diskfull_pending", (char*)&sqlite3_diskfull_pending, TCL_LINK_INT); Tcl_LinkVar(interp, "sqlite_diskfull", diff --git a/src/vacuum.c b/src/vacuum.c index 28d45d5d7..a8af62908 100644 --- a/src/vacuum.c +++ b/src/vacuum.c @@ -14,7 +14,7 @@ ** Most of the code in this file may be omitted by defining the ** SQLITE_OMIT_VACUUM macro. ** -** $Id: vacuum.c,v 1.46 2005/11/03 02:15:04 drh Exp $ +** $Id: vacuum.c,v 1.47 2005/11/04 22:03:30 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -100,6 +100,7 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ Btree *pMain; /* The database being vacuumed */ Btree *pTemp; char *zSql = 0; + int rc2; int saved_flags; /* Saved value of the db->flags */ /* Save the current value of the write-schema flag before setting it. */ @@ -176,7 +177,7 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ #endif /* Begin a transaction */ - rc = execSql(db, "BEGIN;"); + rc = execSql(db, "BEGIN EXCLUSIVE;"); if( rc!=SQLITE_OK ) goto end_of_vacuum; /* Query the schema of the main database. Create a mirror schema @@ -247,7 +248,7 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ ** opened for writing. This way, the SQL transaction used to create the ** temporary database never needs to be committed. */ - if( sqlite3BtreeIsInTrans(pTemp) ){ + if( rc==SQLITE_OK ){ u32 meta; int i; @@ -264,19 +265,21 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ 6, 0, /* Preserve the user version */ }; - assert( 0==sqlite3BtreeIsInTrans(pMain) ); - rc = sqlite3BtreeBeginTrans(pMain, 1); - if( rc!=SQLITE_OK ) goto end_of_vacuum; + assert( 1==sqlite3BtreeIsInTrans(pTemp) ); + assert( 1==sqlite3BtreeIsInTrans(pMain) ); /* Copy Btree meta values */ for(i=0; i<sizeof(aCopy)/sizeof(aCopy[0]); i+=2){ rc = sqlite3BtreeGetMeta(pMain, aCopy[i], &meta); if( rc!=SQLITE_OK ) goto end_of_vacuum; rc = sqlite3BtreeUpdateMeta(pTemp, aCopy[i], meta+aCopy[i+1]); + if( rc!=SQLITE_OK ) goto end_of_vacuum; } rc = sqlite3BtreeCopyFile(pMain, pTemp); if( rc!=SQLITE_OK ) goto end_of_vacuum; + rc = sqlite3BtreeCommit(pTemp); + if( rc!=SQLITE_OK ) goto end_of_vacuum; rc = sqlite3BtreeCommit(pMain); } @@ -292,16 +295,15 @@ end_of_vacuum: ** is closed by the DETACH. */ db->autoCommit = 1; + rc2 = execSql(db, "DETACH vacuum_db;"); if( rc==SQLITE_OK ){ - rc = execSql(db, "DETACH vacuum_db;"); - }else{ - execSql(db, "DETACH vacuum_db;"); + rc = rc2; } if( zTemp ){ sqlite3OsDelete(zTemp); sqliteFree(zTemp); } - if( zSql ) sqliteFree( zSql ); + sqliteFree( zSql ); sqlite3ResetInternalSchema(db, 0); #endif |