summaryrefslogtreecommitdiff
path: root/ext/sqlite/libsqlite/src/vacuum.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/sqlite/libsqlite/src/vacuum.c')
-rw-r--r--ext/sqlite/libsqlite/src/vacuum.c103
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
}