extensions/sqlite/sqlite-source/vacuum.c
branchsourcemod-1.1.0
changeset 2283 03a67e41afbc
parent 1951 c7b4237fff50
child 2287 017a725c9d17
     1.1 --- a/extensions/sqlite/sqlite-source/vacuum.c	Fri Mar 28 06:21:34 2008 +0000
     1.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.3 @@ -1,262 +0,0 @@
     1.4 -/*
     1.5 -** 2003 April 6
     1.6 -**
     1.7 -** The author disclaims copyright to this source code.  In place of
     1.8 -** a legal notice, here is a blessing:
     1.9 -**
    1.10 -**    May you do good and not evil.
    1.11 -**    May you find forgiveness for yourself and forgive others.
    1.12 -**    May you share freely, never taking more than you give.
    1.13 -**
    1.14 -*************************************************************************
    1.15 -** This file contains code used to implement the VACUUM command.
    1.16 -**
    1.17 -** Most of the code in this file may be omitted by defining the
    1.18 -** SQLITE_OMIT_VACUUM macro.
    1.19 -**
    1.20 -** $Id$
    1.21 -*/
    1.22 -#include "sqliteInt.h"
    1.23 -#include "vdbeInt.h"
    1.24 -
    1.25 -#if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH)
    1.26 -/*
    1.27 -** Execute zSql on database db. Return an error code.
    1.28 -*/
    1.29 -static int execSql(sqlite3 *db, const char *zSql){
    1.30 -  sqlite3_stmt *pStmt;
    1.31 -  if( !zSql ){
    1.32 -    return SQLITE_NOMEM;
    1.33 -  }
    1.34 -  if( SQLITE_OK!=sqlite3_prepare(db, zSql, -1, &pStmt, 0) ){
    1.35 -    return sqlite3_errcode(db);
    1.36 -  }
    1.37 -  while( SQLITE_ROW==sqlite3_step(pStmt) ){}
    1.38 -  return sqlite3_finalize(pStmt);
    1.39 -}
    1.40 -
    1.41 -/*
    1.42 -** Execute zSql on database db. The statement returns exactly
    1.43 -** one column. Execute this as SQL on the same database.
    1.44 -*/
    1.45 -static int execExecSql(sqlite3 *db, const char *zSql){
    1.46 -  sqlite3_stmt *pStmt;
    1.47 -  int rc;
    1.48 -
    1.49 -  rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);
    1.50 -  if( rc!=SQLITE_OK ) return rc;
    1.51 -
    1.52 -  while( SQLITE_ROW==sqlite3_step(pStmt) ){
    1.53 -    rc = execSql(db, (char*)sqlite3_column_text(pStmt, 0));
    1.54 -    if( rc!=SQLITE_OK ){
    1.55 -      sqlite3_finalize(pStmt);
    1.56 -      return rc;
    1.57 -    }
    1.58 -  }
    1.59 -
    1.60 -  return sqlite3_finalize(pStmt);
    1.61 -}
    1.62 -
    1.63 -/*
    1.64 -** The non-standard VACUUM command is used to clean up the database,
    1.65 -** collapse free space, etc.  It is modelled after the VACUUM command
    1.66 -** in PostgreSQL.
    1.67 -**
    1.68 -** In version 1.0.x of SQLite, the VACUUM command would call
    1.69 -** gdbm_reorganize() on all the database tables.  But beginning
    1.70 -** with 2.0.0, SQLite no longer uses GDBM so this command has
    1.71 -** become a no-op.
    1.72 -*/
    1.73 -void sqlite3Vacuum(Parse *pParse){
    1.74 -  Vdbe *v = sqlite3GetVdbe(pParse);
    1.75 -  if( v ){
    1.76 -    sqlite3VdbeAddOp(v, OP_Vacuum, 0, 0);
    1.77 -  }
    1.78 -  return;
    1.79 -}
    1.80 -
    1.81 -/*
    1.82 -** This routine implements the OP_Vacuum opcode of the VDBE.
    1.83 -*/
    1.84 -int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
    1.85 -  int rc = SQLITE_OK;     /* Return code from service routines */
    1.86 -  Btree *pMain;           /* The database being vacuumed */
    1.87 -  Btree *pTemp;           /* The temporary database we vacuum into */
    1.88 -  char *zSql = 0;         /* SQL statements */
    1.89 -  int saved_flags;        /* Saved value of the db->flags */
    1.90 -  Db *pDb = 0;            /* Database to detach at end of vacuum */
    1.91 -
    1.92 -  /* Save the current value of the write-schema flag before setting it. */
    1.93 -  saved_flags = db->flags;
    1.94 -  db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks;
    1.95 -
    1.96 -  if( !db->autoCommit ){
    1.97 -    sqlite3SetString(pzErrMsg, "cannot VACUUM from within a transaction", 
    1.98 -       (char*)0);
    1.99 -    rc = SQLITE_ERROR;
   1.100 -    goto end_of_vacuum;
   1.101 -  }
   1.102 -  pMain = db->aDb[0].pBt;
   1.103 -
   1.104 -  /* Attach the temporary database as 'vacuum_db'. The synchronous pragma
   1.105 -  ** can be set to 'off' for this file, as it is not recovered if a crash
   1.106 -  ** occurs anyway. The integrity of the database is maintained by a
   1.107 -  ** (possibly synchronous) transaction opened on the main database before
   1.108 -  ** sqlite3BtreeCopyFile() is called.
   1.109 -  **
   1.110 -  ** An optimisation would be to use a non-journaled pager.
   1.111 -  */
   1.112 -  zSql = "ATTACH '' AS vacuum_db;";
   1.113 -  rc = execSql(db, zSql);
   1.114 -  if( rc!=SQLITE_OK ) goto end_of_vacuum;
   1.115 -  pDb = &db->aDb[db->nDb-1];
   1.116 -  assert( strcmp(db->aDb[db->nDb-1].zName,"vacuum_db")==0 );
   1.117 -  pTemp = db->aDb[db->nDb-1].pBt;
   1.118 -  sqlite3BtreeSetPageSize(pTemp, sqlite3BtreeGetPageSize(pMain),
   1.119 -     sqlite3BtreeGetReserve(pMain));
   1.120 -  if( db->mallocFailed ){
   1.121 -    rc = SQLITE_NOMEM;
   1.122 -    goto end_of_vacuum;
   1.123 -  }
   1.124 -  assert( sqlite3BtreeGetPageSize(pTemp)==sqlite3BtreeGetPageSize(pMain) );
   1.125 -  rc = execSql(db, "PRAGMA vacuum_db.synchronous=OFF");
   1.126 -  if( rc!=SQLITE_OK ){
   1.127 -    goto end_of_vacuum;
   1.128 -  }
   1.129 -
   1.130 -#ifndef SQLITE_OMIT_AUTOVACUUM
   1.131 -  sqlite3BtreeSetAutoVacuum(pTemp, sqlite3BtreeGetAutoVacuum(pMain));
   1.132 -#endif
   1.133 -
   1.134 -  /* Begin a transaction */
   1.135 -  rc = execSql(db, "BEGIN EXCLUSIVE;");
   1.136 -  if( rc!=SQLITE_OK ) goto end_of_vacuum;
   1.137 -
   1.138 -  /* Query the schema of the main database. Create a mirror schema
   1.139 -  ** in the temporary database.
   1.140 -  */
   1.141 -  rc = execExecSql(db, 
   1.142 -      "SELECT 'CREATE TABLE vacuum_db.' || substr(sql,14,100000000) "
   1.143 -      "  FROM sqlite_master WHERE type='table' AND name!='sqlite_sequence'"
   1.144 -      "   AND rootpage>0"
   1.145 -  );
   1.146 -  if( rc!=SQLITE_OK ) goto end_of_vacuum;
   1.147 -  rc = execExecSql(db, 
   1.148 -      "SELECT 'CREATE INDEX vacuum_db.' || substr(sql,14,100000000)"
   1.149 -      "  FROM sqlite_master WHERE sql LIKE 'CREATE INDEX %' ");
   1.150 -  if( rc!=SQLITE_OK ) goto end_of_vacuum;
   1.151 -  rc = execExecSql(db, 
   1.152 -      "SELECT 'CREATE UNIQUE INDEX vacuum_db.' || substr(sql,21,100000000) "
   1.153 -      "  FROM sqlite_master WHERE sql LIKE 'CREATE UNIQUE INDEX %'");
   1.154 -  if( rc!=SQLITE_OK ) goto end_of_vacuum;
   1.155 -
   1.156 -  /* Loop through the tables in the main database. For each, do
   1.157 -  ** an "INSERT INTO vacuum_db.xxx SELECT * FROM xxx;" to copy
   1.158 -  ** the contents to the temporary database.
   1.159 -  */
   1.160 -  rc = execExecSql(db, 
   1.161 -      "SELECT 'INSERT INTO vacuum_db.' || quote(name) "
   1.162 -      "|| ' SELECT * FROM ' || quote(name) || ';'"
   1.163 -      "FROM sqlite_master "
   1.164 -      "WHERE type = 'table' AND name!='sqlite_sequence' "
   1.165 -      "  AND rootpage>0"
   1.166 -
   1.167 -  );
   1.168 -  if( rc!=SQLITE_OK ) goto end_of_vacuum;
   1.169 -
   1.170 -  /* Copy over the sequence table
   1.171 -  */
   1.172 -  rc = execExecSql(db, 
   1.173 -      "SELECT 'DELETE FROM vacuum_db.' || quote(name) || ';' "
   1.174 -      "FROM vacuum_db.sqlite_master WHERE name='sqlite_sequence' "
   1.175 -  );
   1.176 -  if( rc!=SQLITE_OK ) goto end_of_vacuum;
   1.177 -  rc = execExecSql(db, 
   1.178 -      "SELECT 'INSERT INTO vacuum_db.' || quote(name) "
   1.179 -      "|| ' SELECT * FROM ' || quote(name) || ';' "
   1.180 -      "FROM vacuum_db.sqlite_master WHERE name=='sqlite_sequence';"
   1.181 -  );
   1.182 -  if( rc!=SQLITE_OK ) goto end_of_vacuum;
   1.183 -
   1.184 -
   1.185 -  /* Copy the triggers, views, and virtual tables from the main database
   1.186 -  ** over to the temporary database.  None of these objects has any
   1.187 -  ** associated storage, so all we have to do is copy their entries
   1.188 -  ** from the SQLITE_MASTER table.
   1.189 -  */
   1.190 -  rc = execSql(db,
   1.191 -      "INSERT INTO vacuum_db.sqlite_master "
   1.192 -      "  SELECT type, name, tbl_name, rootpage, sql"
   1.193 -      "    FROM sqlite_master"
   1.194 -      "   WHERE type='view' OR type='trigger'"
   1.195 -      "      OR (type='table' AND rootpage=0)"
   1.196 -  );
   1.197 -  if( rc ) goto end_of_vacuum;
   1.198 -
   1.199 -  /* At this point, unless the main db was completely empty, there is now a
   1.200 -  ** transaction open on the vacuum database, but not on the main database.
   1.201 -  ** Open a btree level transaction on the main database. This allows a
   1.202 -  ** call to sqlite3BtreeCopyFile(). The main database btree level
   1.203 -  ** transaction is then committed, so the SQL level never knows it was
   1.204 -  ** opened for writing. This way, the SQL transaction used to create the
   1.205 -  ** temporary database never needs to be committed.
   1.206 -  */
   1.207 -  if( rc==SQLITE_OK ){
   1.208 -    u32 meta;
   1.209 -    int i;
   1.210 -
   1.211 -    /* This array determines which meta meta values are preserved in the
   1.212 -    ** vacuum.  Even entries are the meta value number and odd entries
   1.213 -    ** are an increment to apply to the meta value after the vacuum.
   1.214 -    ** The increment is used to increase the schema cookie so that other
   1.215 -    ** connections to the same database will know to reread the schema.
   1.216 -    */
   1.217 -    static const unsigned char aCopy[] = {
   1.218 -       1, 1,    /* Add one to the old schema cookie */
   1.219 -       3, 0,    /* Preserve the default page cache size */
   1.220 -       5, 0,    /* Preserve the default text encoding */
   1.221 -       6, 0,    /* Preserve the user version */
   1.222 -    };
   1.223 -
   1.224 -    assert( 1==sqlite3BtreeIsInTrans(pTemp) );
   1.225 -    assert( 1==sqlite3BtreeIsInTrans(pMain) );
   1.226 -
   1.227 -    /* Copy Btree meta values */
   1.228 -    for(i=0; i<sizeof(aCopy)/sizeof(aCopy[0]); i+=2){
   1.229 -      rc = sqlite3BtreeGetMeta(pMain, aCopy[i], &meta);
   1.230 -      if( rc!=SQLITE_OK ) goto end_of_vacuum;
   1.231 -      rc = sqlite3BtreeUpdateMeta(pTemp, aCopy[i], meta+aCopy[i+1]);
   1.232 -      if( rc!=SQLITE_OK ) goto end_of_vacuum;
   1.233 -    }
   1.234 -
   1.235 -    rc = sqlite3BtreeCopyFile(pMain, pTemp);
   1.236 -    if( rc!=SQLITE_OK ) goto end_of_vacuum;
   1.237 -    rc = sqlite3BtreeCommit(pTemp);
   1.238 -    if( rc!=SQLITE_OK ) goto end_of_vacuum;
   1.239 -    rc = sqlite3BtreeCommit(pMain);
   1.240 -  }
   1.241 -
   1.242 -end_of_vacuum:
   1.243 -  /* Restore the original value of db->flags */
   1.244 -  db->flags = saved_flags;
   1.245 -
   1.246 -  /* Currently there is an SQL level transaction open on the vacuum
   1.247 -  ** database. No locks are held on any other files (since the main file
   1.248 -  ** was committed at the btree level). So it safe to end the transaction
   1.249 -  ** by manually setting the autoCommit flag to true and detaching the
   1.250 -  ** vacuum database. The vacuum_db journal file is deleted when the pager
   1.251 -  ** is closed by the DETACH.
   1.252 -  */
   1.253 -  db->autoCommit = 1;
   1.254 -
   1.255 -  if( pDb ){
   1.256 -    sqlite3BtreeClose(pDb->pBt);
   1.257 -    pDb->pBt = 0;
   1.258 -    pDb->pSchema = 0;
   1.259 -  }
   1.260 -
   1.261 -  sqlite3ResetInternalSchema(db, 0);
   1.262 -
   1.263 -  return rc;
   1.264 -}
   1.265 -#endif  /* SQLITE_OMIT_VACUUM && SQLITE_OMIT_ATTACH */