diff options
| author | Mark A. Hershberger <mah@debian.(none)> | 2009-03-25 00:37:27 -0400 |
|---|---|---|
| committer | Mark A. Hershberger <mah@debian.(none)> | 2009-03-25 00:37:27 -0400 |
| commit | 2d4e5b09576bb4f0ba716cc82cdf29ea04d9184b (patch) | |
| tree | 41ccc042009cba53e4ce43e727fcba4c1cfbf7f3 /ext/pdo_sqlite/sqlite/src/vacuum.c | |
| parent | d29a4fd2dd3b5d4cf6e80b602544d7b71d794e76 (diff) | |
| download | php-upstream/5.2.2.tar.gz | |
Imported Upstream version 5.2.2upstream/5.2.2
Diffstat (limited to 'ext/pdo_sqlite/sqlite/src/vacuum.c')
| -rw-r--r-- | ext/pdo_sqlite/sqlite/src/vacuum.c | 123 |
1 files changed, 28 insertions, 95 deletions
diff --git a/ext/pdo_sqlite/sqlite/src/vacuum.c b/ext/pdo_sqlite/sqlite/src/vacuum.c index 336df67cc..3f4057382 100644 --- a/ext/pdo_sqlite/sqlite/src/vacuum.c +++ b/ext/pdo_sqlite/sqlite/src/vacuum.c @@ -20,21 +20,7 @@ #include "vdbeInt.h" #include "os.h" -#ifndef SQLITE_OMIT_VACUUM -/* -** Generate a random name of 20 character in length. -*/ -static void randomName(unsigned char *zBuf){ - static const unsigned char zChars[] = - "abcdefghijklmnopqrstuvwxyz" - "0123456789"; - int i; - sqlite3Randomness(20, zBuf); - for(i=0; i<20; i++){ - zBuf[i] = zChars[ zBuf[i]%(sizeof(zChars)-1) ]; - } -} - +#if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH) /* ** Execute zSql on database db. Return an error code. */ @@ -69,8 +55,6 @@ static int execExecSql(sqlite3 *db, const char *zSql){ return sqlite3_finalize(pStmt); } -#endif - /* ** The non-standard VACUUM command is used to clean up the database, ** collapse free space, etc. It is modelled after the VACUUM command @@ -94,15 +78,11 @@ void sqlite3Vacuum(Parse *pParse){ */ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ int rc = SQLITE_OK; /* Return code from service routines */ -#ifndef 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 */ Btree *pMain; /* The database being vacuumed */ - Btree *pTemp; - char *zSql = 0; - int saved_flags; /* Saved value of the db->flags */ - Db *pDb = 0; /* Database to detach at end of vacuum */ + Btree *pTemp; /* The temporary database we vacuum into */ + char *zSql = 0; /* SQL statements */ + int saved_flags; /* Saved value of the db->flags */ + Db *pDb = 0; /* Database to detach at end of vacuum */ /* Save the current value of the write-schema flag before setting it. */ saved_flags = db->flags; @@ -114,40 +94,7 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ rc = SQLITE_ERROR; goto end_of_vacuum; } - - /* Get the full pathname of the database file and create a - ** temporary filename in the same directory as the original file. - */ pMain = db->aDb[0].pBt; - zFilename = sqlite3BtreeGetFilename(pMain); - assert( zFilename ); - if( zFilename[0]=='\0' ){ - /* The in-memory database. Do nothing. Return directly to avoid causing - ** an error trying to DETACH the vacuum_db (which never got attached) - ** in the exit-handler. - */ - return SQLITE_OK; - } - nFilename = strlen(zFilename); - zTemp = sqliteMalloc( nFilename+100 ); - if( zTemp==0 ){ - rc = SQLITE_NOMEM; - goto end_of_vacuum; - } - strcpy(zTemp, zFilename); - - /* The randomName() procedure in the following loop uses an excellent - ** source of randomness to generate a name from a space of 1.3e+31 - ** possibilities. So unless the directory already contains on the order - ** of 1.3e+31 files, the probability that the following loop will - ** run more than once or twice is vanishingly small. We are certain - ** enough that this loop will always terminate (and terminate quickly) - ** that we don't even bother to set a maximum loop count. - */ - do { - zTemp[nFilename] = '-'; - randomName((unsigned char*)&zTemp[nFilename+1]); - } while( sqlite3OsFileExists(zTemp) ); /* Attach the temporary database as 'vacuum_db'. The synchronous pragma ** can be set to 'off' for this file, as it is not recovered if a crash @@ -157,20 +104,18 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ ** ** An optimisation would be to use a non-journaled pager. */ - zSql = sqlite3MPrintf("ATTACH '%q' AS vacuum_db;", zTemp); - if( !zSql ){ - rc = SQLITE_NOMEM; - goto end_of_vacuum; - } + zSql = "ATTACH '' AS vacuum_db;"; rc = execSql(db, zSql); - sqliteFree(zSql); - zSql = 0; if( rc!=SQLITE_OK ) goto end_of_vacuum; pDb = &db->aDb[db->nDb-1]; assert( strcmp(db->aDb[db->nDb-1].zName,"vacuum_db")==0 ); pTemp = db->aDb[db->nDb-1].pBt; sqlite3BtreeSetPageSize(pTemp, sqlite3BtreeGetPageSize(pMain), sqlite3BtreeGetReserve(pMain)); + if( sqlite3MallocFailed() ){ + rc = SQLITE_NOMEM; + goto end_of_vacuum; + } assert( sqlite3BtreeGetPageSize(pTemp)==sqlite3BtreeGetPageSize(pMain) ); rc = execSql(db, "PRAGMA vacuum_db.synchronous=OFF"); if( rc!=SQLITE_OK ){ @@ -190,7 +135,9 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ */ rc = execExecSql(db, "SELECT 'CREATE TABLE vacuum_db.' || substr(sql,14,100000000) " - " FROM sqlite_master WHERE type='table' AND name!='sqlite_sequence'"); + " FROM sqlite_master WHERE type='table' AND name!='sqlite_sequence'" + " AND rootpage>0" + ); if( rc!=SQLITE_OK ) goto end_of_vacuum; rc = execExecSql(db, "SELECT 'CREATE INDEX vacuum_db.' || substr(sql,14,100000000)" @@ -200,11 +147,6 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ "SELECT 'CREATE UNIQUE INDEX vacuum_db.' || substr(sql,21,100000000) " " FROM sqlite_master WHERE sql LIKE 'CREATE UNIQUE INDEX %'"); if( rc!=SQLITE_OK ) goto end_of_vacuum; - rc = execExecSql(db, - "SELECT 'CREATE VIEW vacuum_db.' || substr(sql,13,100000000) " - " FROM sqlite_master WHERE type='view'" - ); - if( rc!=SQLITE_OK ) goto end_of_vacuum; /* Loop through the tables in the main database. For each, do ** an "INSERT INTO vacuum_db.xxx SELECT * FROM xxx;" to copy @@ -214,7 +156,9 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ "SELECT 'INSERT INTO vacuum_db.' || quote(name) " "|| ' SELECT * FROM ' || quote(name) || ';'" "FROM sqlite_master " - "WHERE type = 'table' AND name!='sqlite_sequence';" + "WHERE type = 'table' AND name!='sqlite_sequence' " + " AND rootpage>0" + ); if( rc!=SQLITE_OK ) goto end_of_vacuum; @@ -233,17 +177,19 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ if( rc!=SQLITE_OK ) goto end_of_vacuum; - /* Copy the triggers from the main database to the temporary database. - ** This was deferred before in case the triggers interfered with copying - ** the data. It's possible the indices should be deferred until this - ** point also. + /* Copy the triggers, views, and virtual tables from the main database + ** over to the temporary database. None of these objects has any + ** associated storage, so all we have to do is copy their entries + ** from the SQLITE_MASTER table. */ - rc = execExecSql(db, - "SELECT 'CREATE TRIGGER vacuum_db.' || substr(sql, 16, 1000000) " - "FROM sqlite_master WHERE type='trigger'" + rc = execSql(db, + "INSERT INTO vacuum_db.sqlite_master " + " SELECT type, name, tbl_name, rootpage, sql" + " FROM sqlite_master" + " WHERE type='view' OR type='trigger'" + " OR (type='table' AND rootpage=0)" ); - if( rc!=SQLITE_OK ) goto end_of_vacuum; - + if( rc ) goto end_of_vacuum; /* At this point, unless the main db was completely empty, there is now a ** transaction open on the vacuum database, but not on the main database. @@ -309,21 +255,8 @@ end_of_vacuum: pDb->pSchema = 0; } - /* If one of the execSql() calls above returned SQLITE_NOMEM, then the - ** mallocFailed flag will be clear (because execSql() calls sqlite3_exec()). - ** Fix this so the flag and return code match. - */ - if( rc==SQLITE_NOMEM ){ - sqlite3MallocFailed(); - } - - if( zTemp ){ - sqlite3OsDelete(zTemp); - sqliteFree(zTemp); - } - sqliteFree( zSql ); sqlite3ResetInternalSchema(db, 0); -#endif return rc; } +#endif /* SQLITE_OMIT_VACUUM && SQLITE_OMIT_ATTACH */ |
