aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2005-11-04 22:03:30 +0000
committerdrh <drh@noemail.net>2005-11-04 22:03:30 +0000
commitc9ac5caa457b8115bc64212af8ad8323a65d6d5c (patch)
treecccf1f62c7176c5bb508b7840be4249ddee60a5d /src
parentc01be744bc8e19fa9d74375eba2aab345b296210 (diff)
downloadsqlite-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.h3
-rw-r--r--src/pager.c42
-rw-r--r--src/test2.c5
-rw-r--r--src/vacuum.c22
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