Back to index

php5  5.3.10
Classes | Typedefs | Functions
vacuum.c File Reference
#include "sqliteInt.h"
#include "os.h"

Go to the source code of this file.

Classes

struct  dynStr
struct  vacuumStruct

Typedefs

typedef struct dynStr
typedef struct vacuumStruct

Functions

static void appendText (dynStr *p, const char *zText, int nText)
static void appendQuoted (dynStr *p, const char *zText)
static int execsql (char **pzErrMsg, sqlite *db, const char *zSql)
static int vacuumCallback2 (void *pArg, int argc, char **argv, char **NotUsed)
static int vacuumCallback1 (void *pArg, int argc, char **argv, char **NotUsed)
static void randomName (unsigned char *zBuf)
void sqliteVacuum (Parse *pParse, Token *pTableName)
int sqliteRunVacuum (char **pzErrMsg, sqlite *db)

Class Documentation

struct dynStr

Definition at line 27 of file vacuum.c.

Class Members
int nAlloc
int nUsed
char * z
struct vacuumStruct

Definition at line 37 of file vacuum.c.

Collaboration diagram for vacuumStruct:
Class Members
sqlite * dbNew
sqlite * dbOld
char ** pzErrMsg
int rc
dynStr s1
dynStr s2
const char * zPragma
const char * zTable

Typedef Documentation

typedef struct dynStr

Definition at line 26 of file vacuum.c.

typedef struct vacuumStruct

Definition at line 36 of file vacuum.c.


Function Documentation

static void appendQuoted ( dynStr p,
const char *  zText 
) [static]

Definition at line 71 of file vacuum.c.

                                                      {
  int i, j;
  appendText(p, "'", 1);
  for(i=j=0; zText[i]; i++){
    if( zText[i]=='\'' ){
      appendText(p, &zText[j], i-j+1);
      j = i + 1;
      appendText(p, "'", 1);
    }
  }
  if( j<i ){
    appendText(p, &zText[j], i-j);
  }
  appendText(p, "'", 1);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void appendText ( dynStr p,
const char *  zText,
int  nText 
) [static]

Definition at line 51 of file vacuum.c.

                                                               {
  if( nText<0 ) nText = strlen(zText);
  if( p->z==0 || p->nUsed + nText + 1 >= p->nAlloc ){
    char *zNew;
    p->nAlloc = p->nUsed + nText + 1000;
    zNew = sqliteRealloc(p->z, p->nAlloc);
    if( zNew==0 ){
      sqliteFree(p->z);
      memset(p, 0, sizeof(*p));
      return;
    }
    p->z = zNew;
  }
  memcpy(&p->z[p->nUsed], zText, nText+1);
  p->nUsed += nText;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int execsql ( char **  pzErrMsg,
sqlite db,
const char *  zSql 
) [static]

Definition at line 91 of file vacuum.c.

                                                                 { 
  char *zErrMsg = 0;
  int rc;

  /* printf("***** executing *****\n%s\n", zSql); */
  rc = sqlite_exec(db, zSql, 0, 0, &zErrMsg);
  if( zErrMsg ){
    sqliteSetString(pzErrMsg, zErrMsg, (char*)0);
    sqlite_freemem(zErrMsg);
  }
  return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void randomName ( unsigned char *  zBuf) [static]

Definition at line 169 of file vacuum.c.

                                           {
  static const unsigned char zChars[] =
    "abcdefghijklmnopqrstuvwxyz"
    "0123456789";
  int i;
  sqliteRandomness(20, zBuf);
  for(i=0; i<20; i++){
    zBuf[i] = zChars[ zBuf[i]%(sizeof(zChars)-1) ];
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

int sqliteRunVacuum ( char **  pzErrMsg,
sqlite db 
)

Definition at line 200 of file vacuum.c.

                                                {
#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 */
  int rc = SQLITE_OK;     /* Return code from service routines */
  int i;                  /* Loop counter */
  char *zErrMsg;          /* Error message */
  vacuumStruct sVac;      /* Information passed to callbacks */

  if( db->flags & SQLITE_InTrans ){
    sqliteSetString(pzErrMsg, "cannot VACUUM from within a transaction", 
       (char*)0);
    return SQLITE_ERROR;
  }
  if( db->flags & SQLITE_Interrupt ){
    return SQLITE_INTERRUPT;
  }
  memset(&sVac, 0, sizeof(sVac));

  /* Get the full pathname of the database file and create two
  ** temporary filenames in the same directory as the original file.
  */
  zFilename = sqliteBtreeGetFilename(db->aDb[0].pBt);
  if( zFilename==0 ){
    /* This only happens with the in-memory database.  VACUUM is a no-op
    ** there, so just return */
    return SQLITE_OK;
  }
  nFilename = strlen(zFilename);
  zTemp = sqliteMalloc( nFilename+100 );
  if( zTemp==0 ) return SQLITE_NOMEM;
  strcpy(zTemp, zFilename);
  for(i=0; i<10; i++){
    zTemp[nFilename] = '-';
    randomName((unsigned char*)&zTemp[nFilename+1]);
    if( !sqliteOsFileExists(zTemp) ) break;
  }
  if( i>=10 ){
    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 ){
    sqliteSetString(pzErrMsg, "unable to open a temporary database at ",
       zTemp, " - ", zErrMsg, (char*)0);
    goto end_of_vacuum;
  }
  if( (rc = execsql(pzErrMsg, db, "BEGIN"))!=0 ) goto end_of_vacuum;
  if( (rc = execsql(pzErrMsg, dbNew, "PRAGMA synchronous=off; BEGIN"))!=0 ){
    goto end_of_vacuum;
  }
  
  sVac.dbOld = db;
  sVac.dbNew = dbNew;
  sVac.pzErrMsg = pzErrMsg;
  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==SQLITE_OK ){
    int meta1[SQLITE_N_BTREE_META];
    int meta2[SQLITE_N_BTREE_META];
    sqliteBtreeGetMeta(db->aDb[0].pBt, meta1);
    sqliteBtreeGetMeta(dbNew->aDb[0].pBt, meta2);
    meta2[1] = meta1[1]+1;
    meta2[3] = meta1[3];
    meta2[4] = meta1[4];
    meta2[6] = meta1[6];
    rc = sqliteBtreeUpdateMeta(dbNew->aDb[0].pBt, meta2);
  }
  if( rc==SQLITE_OK ){
    rc = sqliteBtreeCopyFile(db->aDb[0].pBt, dbNew->aDb[0].pBt);
    sqlite_exec(db, "COMMIT", 0, 0, 0);
    sqliteResetInternalSchema(db, 0);
  }

end_of_vacuum:
  if( rc && zErrMsg!=0 ){
    sqliteSetString(pzErrMsg, "unable to vacuum database - ", 
       zErrMsg, (char*)0);
  }
  sqlite_exec(db, "ROLLBACK", 0, 0, 0);
  if( (dbNew && (dbNew->flags & SQLITE_Interrupt)) 
         || (db->flags & SQLITE_Interrupt) ){
    rc = SQLITE_INTERRUPT;
  }
  if( dbNew ) sqlite_close(dbNew);
  sqliteOsDelete(zTemp);
  sqliteFree(zTemp);
  sqliteFree(sVac.s1.z);
  sqliteFree(sVac.s2.z);
  if( zErrMsg ) sqlite_freemem(zErrMsg);
  if( rc==SQLITE_ABORT && sVac.rc!=SQLITE_INTERRUPT ) sVac.rc = SQLITE_ERROR;
  return sVac.rc;
#endif
}

Here is the call graph for this function:

Here is the caller graph for this function:

void sqliteVacuum ( Parse pParse,
Token pTableName 
)

Definition at line 191 of file vacuum.c.

                                                   {
  Vdbe *v = sqliteGetVdbe(pParse);
  sqliteVdbeAddOp(v, OP_Vacuum, 0, 0);
  return;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int vacuumCallback1 ( void *  pArg,
int  argc,
char **  argv,
char **  NotUsed 
) [static]

Definition at line 141 of file vacuum.c.

                                                                             {
  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->pzErrMsg, p->dbNew, argv[2]);
  if( rc==SQLITE_OK && strcmp(argv[0],"table")==0 ){
    char *zErrMsg = 0;
    p->s1.nUsed = 0;
    appendText(&p->s1, "SELECT * FROM ", -1);
    appendQuoted(&p->s1, argv[1]);
    p->zTable = argv[1];
    rc = sqlite_exec(p->dbOld, p->s1.z, vacuumCallback2, p, &zErrMsg);
    if( zErrMsg ){
      sqliteSetString(p->pzErrMsg, zErrMsg, (char*)0);
      sqlite_freemem(zErrMsg);
    }
  }
  if( rc!=SQLITE_ABORT ) p->rc = rc;
  return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int vacuumCallback2 ( void *  pArg,
int  argc,
char **  argv,
char **  NotUsed 
) [static]

Definition at line 109 of file vacuum.c.

                                                                             {
  vacuumStruct *p = (vacuumStruct*)pArg;
  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);
  appendText(&p->s2, " VALUES", -1);
  for(i=0; i<argc; i++){
    appendText(&p->s2, zSep, 1);
    zSep = ",";
    if( argv[i]==0 ){
      appendText(&p->s2, "NULL", 4);
    }else{
      appendQuoted(&p->s2, argv[i]);
    }
  }
  appendText(&p->s2,")", 1);
  p->rc = execsql(p->pzErrMsg, p->dbNew, p->s2.z);
  return p->rc;
}

Here is the call graph for this function:

Here is the caller graph for this function: