Пример #1
0
int sqliteRbtreeOpen(
  const char *zFilename,
  int mode,
  int nPg,
  Btree **ppBtree
){
  Rbtree **ppRbtree = (Rbtree**)ppBtree;
  *ppRbtree = (Rbtree *)sqliteMalloc(sizeof(Rbtree));
  if( sqlite_malloc_failed ) goto open_no_mem;
  sqliteHashInit(&(*ppRbtree)->tblHash, SQLITE_HASH_INT, 0);

  /* Create a binary tree for the SQLITE_MASTER table at location 2 */
  btreeCreateTable(*ppRbtree, 2);
  if( sqlite_malloc_failed ) goto open_no_mem;
  (*ppRbtree)->next_idx = 3;
  (*ppRbtree)->pOps = &sqliteRbtreeOps;
  /* Set file type to 4; this is so that "attach ':memory:' as ...."  does not
  ** think that the database in uninitialised and refuse to attach
  */
  (*ppRbtree)->aMetaData[2] = 4;
  
  return SQLITE_OK;

open_no_mem:
  *ppBtree = 0;
  return SQLITE_NOMEM;
}
Пример #2
0
/*
** This routine is called by the parser to process an ATTACH statement:
**
**     ATTACH DATABASE filename AS dbname
**
** The pFilename and pDbname arguments are the tokens that define the
** filename and dbname in the ATTACH statement.
*/
void sqliteAttach(Parse *pParse, Token *pFilename, Token *pDbname, Token *pKey){
  Db *aNew;
  int rc, i;
  char *zFile, *zName;
  sqlite *db;
  Vdbe *v;

  v = sqliteGetVdbe(pParse);
  sqliteVdbeAddOp(v, OP_Halt, 0, 0);
  if( pParse->explain ) return;
  db = pParse->db;
  if( db->file_format<4 ){
    sqliteErrorMsg(pParse, "cannot attach auxiliary databases to an "
       "older format master database", 0);
    pParse->rc = SQLITE_ERROR;
    return;
  }
  if( db->nDb>=MAX_ATTACHED+2 ){
    sqliteErrorMsg(pParse, "too many attached databases - max %d", 
       MAX_ATTACHED);
    pParse->rc = SQLITE_ERROR;
    return;
  }

  zFile = 0;
  sqliteSetNString(&zFile, pFilename->z, pFilename->n, 0);
  if( zFile==0 ) return;
  sqliteDequote(zFile);
#ifndef SQLITE_OMIT_AUTHORIZATION
  if( sqliteAuthCheck(pParse, SQLITE_ATTACH, zFile, 0, 0)!=SQLITE_OK ){
    sqliteFree(zFile);
    return;
  }
#endif /* SQLITE_OMIT_AUTHORIZATION */

  zName = 0;
  sqliteSetNString(&zName, pDbname->z, pDbname->n, 0);
  if( zName==0 ) return;
  sqliteDequote(zName);
  for(i=0; i<db->nDb; i++){
    if( db->aDb[i].zName && sqliteStrICmp(db->aDb[i].zName, zName)==0 ){
      sqliteErrorMsg(pParse, "database %z is already in use", zName);
      pParse->rc = SQLITE_ERROR;
      sqliteFree(zFile);
      return;
    }
  }

  if( db->aDb==db->aDbStatic ){
    aNew = sqliteMalloc( sizeof(db->aDb[0])*3 );
    if( aNew==0 ) return;
    memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2);
  }else{
    aNew = sqliteRealloc(db->aDb, sizeof(db->aDb[0])*(db->nDb+1) );
    if( aNew==0 ) return;
  }
  db->aDb = aNew;
  aNew = &db->aDb[db->nDb++];
  memset(aNew, 0, sizeof(*aNew));
  sqliteHashInit(&aNew->tblHash, SQLITE_HASH_STRING, 0);
  sqliteHashInit(&aNew->idxHash, SQLITE_HASH_STRING, 0);
  sqliteHashInit(&aNew->trigHash, SQLITE_HASH_STRING, 0);
  sqliteHashInit(&aNew->aFKey, SQLITE_HASH_STRING, 1);
  aNew->zName = zName;
  rc = sqliteBtreeFactory(db, zFile, 0, MAX_PAGES, &aNew->pBt);
  if( rc ){
    sqliteErrorMsg(pParse, "unable to open database: %s", zFile);
  }
#if SQLITE_HAS_CODEC
  {
    extern int sqliteCodecAttach(sqlite*, int, void*, int);
    char *zKey = 0;
    int nKey;
    if( pKey && pKey->z && pKey->n ){
      sqliteSetNString(&zKey, pKey->z, pKey->n, 0);
      sqliteDequote(zKey);
      nKey = strlen(zKey);
    }else{
      zKey = 0;
      nKey = 0;
    }
    sqliteCodecAttach(db, db->nDb-1, zKey, nKey);
  }
#endif
  sqliteFree(zFile);
  db->flags &= ~SQLITE_Initialized;
  if( pParse->nErr ) return;
  if( rc==SQLITE_OK ){
    rc = sqliteInit(pParse->db, &pParse->zErrMsg);
  }
  if( rc ){
    int i = db->nDb - 1;
    assert( i>=2 );
    if( db->aDb[i].pBt ){
      sqliteBtreeClose(db->aDb[i].pBt);
      db->aDb[i].pBt = 0;
    }
    sqliteResetInternalSchema(db, 0);
    pParse->nErr++;
    pParse->rc = SQLITE_ERROR;
  }
}
Пример #3
0
/*
** Open a new SQLite database.  Construct an "sqlite" structure to define
** the state of this database and return a pointer to that structure.
**
** An attempt is made to initialize the in-memory data structures that
** hold the database schema.  But if this fails (because the schema file
** is locked) then that step is deferred until the first call to
** sqlite_exec().
*/
sqlite *sqlite_open(const char *zFilename, int mode, char **pzErrMsg){
  sqlite *db;
  int rc, i;

  /* Allocate the sqlite data structure */
  db = sqliteMalloc( sizeof(sqlite) );
  if( pzErrMsg ) *pzErrMsg = 0;
  if( db==0 ) goto no_mem_on_open;
  db->onError = OE_Default;
  db->priorNewRowid = 0;
  db->magic = SQLITE_MAGIC_BUSY;
  db->nDb = 2;
  db->aDb = db->aDbStatic;
  /* db->flags |= SQLITE_ShortColNames; */
  sqliteHashInit(&db->aFunc, SQLITE_HASH_STRING, 1);
  for(i=0; i<db->nDb; i++){
    sqliteHashInit(&db->aDb[i].tblHash, SQLITE_HASH_STRING, 0);
    sqliteHashInit(&db->aDb[i].idxHash, SQLITE_HASH_STRING, 0);
    sqliteHashInit(&db->aDb[i].trigHash, SQLITE_HASH_STRING, 0);
    sqliteHashInit(&db->aDb[i].aFKey, SQLITE_HASH_STRING, 1);
  }
  
  /* Open the backend database driver */
  if( zFilename[0]==':' && strcmp(zFilename,":memory:")==0 ){
    db->temp_store = 2;
  }
  rc = sqliteBtreeFactory(db, zFilename, 0, MAX_PAGES, &db->aDb[0].pBt);
  if( rc!=SQLITE_OK ){
    switch( rc ){
      default: {
        sqliteSetString(pzErrMsg, "unable to open database: ",
           zFilename, (char*)0);
      }
    }
    sqliteFree(db);
    sqliteStrRealloc(pzErrMsg);
    return 0;
  }
  db->aDb[0].zName = "main";
  db->aDb[1].zName = "temp";

  /* Attempt to read the schema */
  sqliteRegisterBuiltinFunctions(db);
  rc = sqliteInit(db, pzErrMsg);
  db->magic = SQLITE_MAGIC_OPEN;
  if( sqlite_malloc_failed ){
    sqlite_close(db);
    goto no_mem_on_open;
  }else if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){
    sqlite_close(db);
    sqliteStrRealloc(pzErrMsg);
    return 0;
  }else if( pzErrMsg ){
    sqliteFree(*pzErrMsg);
    *pzErrMsg = 0;
  }

  /* Return a pointer to the newly opened database structure */
  return db;

no_mem_on_open:
  sqliteSetString(pzErrMsg, "out of memory", (char*)0);
  sqliteStrRealloc(pzErrMsg);
  return 0;
}
Пример #4
0
/*
** Prepare a virtual machine for execution.  This involves things such
** as allocating stack space and initializing the program counter.
** After the VDBE has be prepped, it can be executed by one or more
** calls to sqliteVdbeExec().  
*/
void sqliteVdbeMakeReady(
  Vdbe *p,                       /* The VDBE */
  int nVar,                      /* Number of '?' see in the SQL statement */
  int isExplain                  /* True if the EXPLAIN keywords is present */
){
  int n;

  assert( p!=0 );
  assert( p->magic==VDBE_MAGIC_INIT );

  /* Add a HALT instruction to the very end of the program.
  */
  if( p->nOp==0 || (p->aOp && p->aOp[p->nOp-1].opcode!=OP_Halt) ){
    sqliteVdbeAddOp(p, OP_Halt, 0, 0);
  }

  /* No instruction ever pushes more than a single element onto the
  ** stack.  And the stack never grows on successive executions of the
  ** same loop.  So the total number of instructions is an upper bound
  ** on the maximum stack depth required.
  **
  ** Allocation all the stack space we will ever need.
  */
  if( p->aStack==0 ){
    p->nVar = nVar;
    assert( nVar>=0 );
    n = isExplain ? 10 : p->nOp;
    p->aStack = sqliteMalloc(
      n*(sizeof(p->aStack[0]) + 2*sizeof(char*))     /* aStack and zArgv */
        + p->nVar*(sizeof(char*)+sizeof(int)+1)    /* azVar, anVar, abVar */
    );
    p->zArgv = (char**)&p->aStack[n];
    p->azColName = (char**)&p->zArgv[n];
    p->azVar = (char**)&p->azColName[n];
    p->anVar = (int*)&p->azVar[p->nVar];
    p->abVar = (u8*)&p->anVar[p->nVar];
  }

  sqliteHashInit(&p->agg.hash, SQLITE_HASH_BINARY, 0);
  p->agg.pSearch = 0;
#ifdef MEMORY_DEBUG
  if( sqliteOsFileExists("vdbe_trace") ){
    p->trace = stdout;
  }
#endif
  p->pTos = &p->aStack[-1];
  p->pc = 0;
  p->rc = SQLITE_OK;
  p->uniqueCnt = 0;
  p->returnDepth = 0;
  p->errorAction = OE_Abort;
  p->undoTransOnError = 0;
  p->popStack =  0;
  p->explain |= isExplain;
  p->magic = VDBE_MAGIC_RUN;
#ifdef VDBE_PROFILE
  {
    int i;
    for(i=0; i<p->nOp; i++){
      p->aOp[i].cnt = 0;
      p->aOp[i].cycles = 0;
    }
  }
#endif
}