diff options
Diffstat (limited to 'ext/sqlite/libsqlite/src/vacuum.c')
-rw-r--r-- | ext/sqlite/libsqlite/src/vacuum.c | 103 |
1 files changed, 54 insertions, 49 deletions
diff --git a/ext/sqlite/libsqlite/src/vacuum.c b/ext/sqlite/libsqlite/src/vacuum.c index 145b368508..9cad4008e6 100644 --- a/ext/sqlite/libsqlite/src/vacuum.c +++ b/ext/sqlite/libsqlite/src/vacuum.c @@ -37,7 +37,8 @@ typedef struct vacuumStruct vacuumStruct; struct vacuumStruct { sqlite *dbOld; /* Original database */ sqlite *dbNew; /* New database */ - Parse *pParse; /* The parser context */ + char **pzErrMsg; /* Write errors here */ + int rc; /* Set to non-zero on an error */ const char *zTable; /* Name of a table being copied */ const char *zPragma; /* Pragma to execute with results */ dynStr s1, s2; /* Two dynamic strings */ @@ -85,16 +86,16 @@ static void appendQuoted(dynStr *p, const char *zText){ /* ** Execute statements of SQL. If an error occurs, write the error -** message into pParse->zErrMsg and return non-zero. +** message into *pzErrMsg and return non-zero. */ -static int execsql(Parse *pParse, sqlite *db, const char *zSql){ - int rc; +static int execsql(char **pzErrMsg, sqlite *db, const char *zSql){ char *zErrMsg = 0; + int rc; /* printf("***** executing *****\n%s\n", zSql); */ rc = sqlite_exec(db, zSql, 0, 0, &zErrMsg); - if( rc ){ - sqliteErrorMsg(pParse, "%s", zErrMsg); + if( zErrMsg ){ + sqliteSetString(pzErrMsg, zErrMsg, (char*)0); sqlite_freemem(zErrMsg); } return rc; @@ -111,6 +112,7 @@ static int vacuumCallback2(void *pArg, int argc, char **argv, char **NotUsed){ const char *zSep = "("; int i; + if( argv==0 ) return 0; p->s2.nUsed = 0; appendText(&p->s2, "INSERT INTO ", -1); appendQuoted(&p->s2, p->zTable); @@ -125,7 +127,7 @@ static int vacuumCallback2(void *pArg, int argc, char **argv, char **NotUsed){ } } appendText(&p->s2,")", 1); - rc = execsql(p->pParse, p->dbNew, p->s2.z); + rc = execsql(p->pzErrMsg, p->dbNew, p->s2.z); return rc; } @@ -141,10 +143,11 @@ static int vacuumCallback1(void *pArg, int argc, char **argv, char **NotUsed){ vacuumStruct *p = (vacuumStruct*)pArg; int rc = 0; assert( argc==3 ); + if( argv==0 ) return 0; assert( argv[0]!=0 ); assert( argv[1]!=0 ); assert( argv[2]!=0 ); - rc = execsql(p->pParse, p->dbNew, argv[2]); + rc = execsql(p->pzErrMsg, p->dbNew, argv[2]); if( rc==SQLITE_OK && strcmp(argv[0],"table")==0 ){ char *zErrMsg = 0; p->s1.nUsed = 0; @@ -152,8 +155,9 @@ static int vacuumCallback1(void *pArg, int argc, char **argv, char **NotUsed){ appendQuoted(&p->s1, argv[1]); p->zTable = argv[1]; rc = sqlite_exec(p->dbOld, p->s1.z, vacuumCallback2, p, &zErrMsg); - if( rc && p->pParse->zErrMsg==0 ){ - sqliteErrorMsg(p->pParse, "%s", zErrMsg); + if( zErrMsg ){ + sqliteSetString(p->pzErrMsg, zErrMsg, (char*)0); + sqlite_freemem(zErrMsg); } } return rc; @@ -169,11 +173,12 @@ static int vacuumCallback3(void *pArg, int argc, char **argv, char **NotUsed){ int rc = 0; char zBuf[200]; assert( argc==1 ); + if( argv==0 ) return 0; assert( argv[0]!=0 ); assert( strlen(p->zPragma)<100 ); assert( strlen(argv[0])<30 ); sprintf(zBuf,"PRAGMA %s=%s;", p->zPragma, argv[0]); - rc = execsql(p->pParse, p->dbNew, zBuf); + rc = execsql(p->pzErrMsg, p->dbNew, zBuf); return rc; } @@ -203,16 +208,23 @@ static void randomName(char *zBuf){ ** become a no-op. */ void sqliteVacuum(Parse *pParse, Token *pTableName){ + Vdbe *v = sqliteGetVdbe(pParse); + sqliteVdbeAddOp(v, OP_Vacuum, 0, 0); + return; +} + +/* +** This routine implements the OP_Vacuum opcode of the VDBE. +*/ +int sqliteRunVacuum(char **pzErrMsg, sqlite *db){ #if !defined(SQLITE_OMIT_VACUUM) || 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 */ + char *zErrMsg; /* Error message */ vacuumStruct sVac; /* Information passed to callbacks */ /* These are all of the pragmas that need to be transferred over @@ -223,15 +235,10 @@ void sqliteVacuum(Parse *pParse, Token *pTableName){ /* "default_temp_store", */ }; - /* Initial error checks - */ - if( pParse->explain ){ - return; - } - db = pParse->db; if( db->flags & SQLITE_InTrans ){ - sqliteErrorMsg(pParse, "cannot VACUUM from within a transaction"); - return; + sqliteSetString(pzErrMsg, "cannot VACUUM from within a transaction", + (char*)0); + return SQLITE_ERROR; } memset(&sVac, 0, sizeof(sVac)); @@ -242,11 +249,11 @@ void sqliteVacuum(Parse *pParse, Token *pTableName){ if( zFilename==0 ){ /* This only happens with the in-memory database. VACUUM is a no-op ** there, so just return */ - return; + return SQLITE_OK; } nFilename = strlen(zFilename); zTemp = sqliteMalloc( nFilename+100 ); - if( zTemp==0 ) return; + if( zTemp==0 ) return SQLITE_NOMEM; strcpy(zTemp, zFilename); for(i=0; i<10; i++){ zTemp[nFilename] = '-'; @@ -254,30 +261,26 @@ void sqliteVacuum(Parse *pParse, Token *pTableName){ if( !sqliteOsFileExists(zTemp) ) break; } if( i>=10 ){ - sqliteErrorMsg(pParse, "unable to create a temporary database file " - "in the same directory as the original database"); + sqliteSetString(pzErrMsg, "unable to create a temporary database file " + "in the same directory as the original database", (char*)0); 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"); + sqliteSetString(pzErrMsg, "unable to open a temporary database at ", + zTemp, " - ", zErrMsg, (char*)0); goto end_of_vacuum; } - safety = 1; - if( execsql(pParse, db, "BEGIN") ) goto end_of_vacuum; - if( execsql(pParse, dbNew, "PRAGMA synchronous=off; BEGIN") ){ + if( execsql(pzErrMsg, db, "BEGIN") ) goto end_of_vacuum; + if( execsql(pzErrMsg, dbNew, "PRAGMA synchronous=off; BEGIN") ){ goto end_of_vacuum; } + sVac.dbOld = db; sVac.dbNew = dbNew; - sVac.pParse = pParse; + sVac.pzErrMsg = pzErrMsg; for(i=0; rc==SQLITE_OK && i<sizeof(zPragma)/sizeof(zPragma[0]); i++){ char zBuf[200]; assert( strlen(zPragma[i])<100 ); @@ -285,32 +288,34 @@ void sqliteVacuum(Parse *pParse, Token *pTableName){ sVac.zPragma = zPragma[i]; rc = sqlite_exec(db, zBuf, vacuumCallback3, &sVac, &zErrMsg); } - if( !rc ){ - rc = sqlite_exec(db, "SELECT type, name, sql FROM sqlite_master " - "WHERE sql NOT NULL", vacuumCallback1, &sVac, &zErrMsg); + if( rc==SQLITE_OK ){ + rc = sqlite_exec(db, + "SELECT type, name, sql FROM sqlite_master " + "WHERE sql NOT NULL AND type!='view' " + "UNION ALL " + "SELECT type, name, sql FROM sqlite_master " + "WHERE sql NOT NULL AND type=='view'", + vacuumCallback1, &sVac, &zErrMsg); } - if( !rc ){ + if( rc==SQLITE_OK ){ rc = sqliteBtreeCopyFile(db->aDb[0].pBt, dbNew->aDb[0].pBt); sqlite_exec(db, "COMMIT", 0, 0, 0); - sqlite_exec(db, "ROLLBACK", 0, 0, 0); /* In case the COMMIT failed */ sqliteResetInternalSchema(db, 0); } end_of_vacuum: - if( rc && pParse->zErrMsg==0 && zErrMsg!=0 ){ - sqliteErrorMsg(pParse, "unable to vacuum database - %s", zErrMsg); - } - if( safety ) { - sqlite_exec(db, "COMMIT", 0, 0, 0); - sqlite_exec(db, "ROLLBACK", 0, 0, 0); /* In case the COMMIT failed */ - sqliteSafetyOn(db); + if( rc && zErrMsg!=0 ){ + sqliteSetString(pzErrMsg, "unable to vacuum database - ", + zErrMsg, (char*)0); } + sqlite_exec(db, "ROLLBACK", 0, 0, 0); if( dbNew ) sqlite_close(dbNew); sqliteOsDelete(zTemp); sqliteFree(zTemp); sqliteFree(sVac.s1.z); sqliteFree(sVac.s2.z); if( zErrMsg ) sqlite_freemem(zErrMsg); - return; + if( rc==SQLITE_ABORT ) rc = SQLITE_ERROR; + return rc; #endif } |