예제 #1
0
파일: legacy.c 프로젝트: Adoni/WiEngine
/*
** Execute SQL code.  Return one of the SQLITE_ success/failure
** codes.  Also write an error message into memory obtained from
** malloc() and make *pzErrMsg point to that message.
**
** If the SQL is a query, then for each row in the query result
** the xCallback() function is called.  pArg becomes the first
** argument to xCallback().  If xCallback=NULL then no callback
** is invoked, even for queries.
*/
int sqlite3_exec(
  sqlite3 *db,                /* The database on which the SQL executes */
  const char *zSql,           /* The SQL to be executed */
  sqlite3_callback xCallback, /* Invoke this callback routine */
  void *pArg,                 /* First argument to xCallback() */
  char **pzErrMsg             /* Write error messages here */
){
  int rc = SQLITE_OK;         /* Return code */
  const char *zLeftover;      /* Tail of unprocessed SQL */
  sqlite3_stmt *pStmt = 0;    /* The current SQL statement */
  char **azCols = 0;          /* Names of result columns */
  int nRetry = 0;             /* Number of retry attempts */
  int callbackIsInit;         /* True if callback data is initialized */

  if( zSql==0 ) zSql = "";

  sqlite3_mutex_enter(db->mutex);
  sqlite3Error(db, SQLITE_OK, 0);
  while( (rc==SQLITE_OK || (rc==SQLITE_SCHEMA && (++nRetry)<2)) && zSql[0] ){
    int nCol;
    char **azVals = 0;

    pStmt = 0;
    rc = sqlite3_prepare(db, zSql, -1, &pStmt, &zLeftover);
    assert( rc==SQLITE_OK || pStmt==0 );
    if( rc!=SQLITE_OK ){
      continue;
    }
    if( !pStmt ){
      /* this happens for a comment or white-space */
      zSql = zLeftover;
      continue;
    }

    callbackIsInit = 0;
    nCol = sqlite3_column_count(pStmt);

    while( 1 ){
      int i;
      rc = sqlite3_step(pStmt);

      /* Invoke the callback function if required */
      if( xCallback && (SQLITE_ROW==rc || 
          (SQLITE_DONE==rc && !callbackIsInit
                           && db->flags&SQLITE_NullCallback)) ){
        if( !callbackIsInit ){
          azCols = sqlite3DbMallocZero(db, 2*nCol*sizeof(const char*) + 1);
          if( azCols==0 ){
            goto exec_out;
          }
          for(i=0; i<nCol; i++){
            azCols[i] = (char *)sqlite3_column_name(pStmt, i);
            /* sqlite3VdbeSetColName() installs column names as UTF8
            ** strings so there is no way for sqlite3_column_name() to fail. */
            assert( azCols[i]!=0 );
          }
          callbackIsInit = 1;
        }
        if( rc==SQLITE_ROW ){
          azVals = &azCols[nCol];
          for(i=0; i<nCol; i++){
            azVals[i] = (char *)sqlite3_column_text(pStmt, i);
            if( !azVals[i] && sqlite3_column_type(pStmt, i)!=SQLITE_NULL ){
              db->mallocFailed = 1;
              goto exec_out;
            }
          }
        }
        if( xCallback(pArg, nCol, azVals, azCols) ){
          rc = SQLITE_ABORT;
          sqlite3VdbeFinalize((Vdbe *)pStmt);
          pStmt = 0;
          sqlite3Error(db, SQLITE_ABORT, 0);
          goto exec_out;
        }
      }

      if( rc!=SQLITE_ROW ){
        rc = sqlite3VdbeFinalize((Vdbe *)pStmt);
        pStmt = 0;
        if( rc!=SQLITE_SCHEMA ){
          nRetry = 0;
          zSql = zLeftover;
          while( sqlite3Isspace(zSql[0]) ) zSql++;
        }
        break;
      }
    }

    sqlite3DbFree(db, azCols);
    azCols = 0;
  }

exec_out:
  if( pStmt ) sqlite3VdbeFinalize((Vdbe *)pStmt);
  sqlite3DbFree(db, azCols);

  rc = sqlite3ApiExit(db, rc);
  if( rc!=SQLITE_OK && ALWAYS(rc==sqlite3_errcode(db)) && pzErrMsg ){
    int nErrMsg = 1 + sqlite3Strlen30(sqlite3_errmsg(db));
    *pzErrMsg = sqlite3Malloc(nErrMsg);
    if( *pzErrMsg ){
      memcpy(*pzErrMsg, sqlite3_errmsg(db), nErrMsg);
    }else{
      rc = SQLITE_NOMEM;
      sqlite3Error(db, SQLITE_NOMEM, 0);
    }
  }else if( pzErrMsg ){
    *pzErrMsg = 0;
  }

  assert( (rc&db->errMask)==rc );
  sqlite3_mutex_leave(db->mutex);
  return rc;
}
예제 #2
0
/*
** Compile the UTF-8 encoded SQL statement zSql into a statement handle.
*/
int sqlite3_prepare(
  sqlite3 *db,              /* Database handle. */
  const char *zSql,         /* UTF-8 encoded SQL statement. */
  int nBytes,               /* Length of zSql in bytes. */
  sqlite3_stmt **ppStmt,    /* OUT: A pointer to the prepared statement */
  const char** pzTail       /* OUT: End of parsed string */
){
  Parse sParse;
  char *zErrMsg = 0;
  int rc = SQLITE_OK;

  if( sqlite3_malloc_failed ){
    return SQLITE_NOMEM;
  }

  assert( ppStmt );
  *ppStmt = 0;
  if( sqlite3SafetyOn(db) ){
    return SQLITE_MISUSE;
  }

  memset(&sParse, 0, sizeof(sParse));
  sParse.db = db;
  sqlite3RunParser(&sParse, zSql, &zErrMsg);

  if( sqlite3_malloc_failed ){
    rc = SQLITE_NOMEM;
    sqlite3RollbackAll(db);
    sqlite3ResetInternalSchema(db, 0);
    db->flags &= ~SQLITE_InTrans;
    goto prepare_out;
  }
  if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK;
  if( sParse.rc!=SQLITE_OK && sParse.checkSchema && !schemaIsValid(db) ){
    sParse.rc = SQLITE_SCHEMA;
  }
  if( sParse.rc==SQLITE_SCHEMA ){
    sqlite3ResetInternalSchema(db, 0);
  }
  if( pzTail ) *pzTail = sParse.zTail;
  rc = sParse.rc;

#ifndef SQLITE_OMIT_EXPLAIN
  if( rc==SQLITE_OK && sParse.pVdbe && sParse.explain ){
    sqlite3VdbeSetNumCols(sParse.pVdbe, 5);
    sqlite3VdbeSetColName(sParse.pVdbe, 0, "addr", P3_STATIC);
    sqlite3VdbeSetColName(sParse.pVdbe, 1, "opcode", P3_STATIC);
    sqlite3VdbeSetColName(sParse.pVdbe, 2, "p1", P3_STATIC);
    sqlite3VdbeSetColName(sParse.pVdbe, 3, "p2", P3_STATIC);
    sqlite3VdbeSetColName(sParse.pVdbe, 4, "p3", P3_STATIC);
  } 
#endif

prepare_out:
  if( sqlite3SafetyOff(db) ){
    rc = SQLITE_MISUSE;
  }
  if( rc==SQLITE_OK ){
    *ppStmt = (sqlite3_stmt*)sParse.pVdbe;
  }else if( sParse.pVdbe ){
    sqlite3_finalize((sqlite3_stmt*)sParse.pVdbe);
  }

  if( zErrMsg ){
    sqlite3Error(db, rc, "%s", zErrMsg);
    sqliteFree(zErrMsg);
  }else{
    sqlite3Error(db, rc, 0);
  }
  return rc;
}
예제 #3
0
파일: prepare.c 프로젝트: DrEastex/Platinum
/*
** Compile the UTF-8 encoded SQL statement zSql into a statement handle.
*/
int sqlite3_prepare(
  sqlite3 *db,              /* Database handle. */
  const char *zSql,         /* UTF-8 encoded SQL statement. */
  int nBytes,               /* Length of zSql in bytes. */
  sqlite3_stmt **ppStmt,    /* OUT: A pointer to the prepared statement */
  const char** pzTail       /* OUT: End of parsed string */
){
  Parse sParse;
  char *zErrMsg = 0;
  int rc = SQLITE_OK;
  int i;

  /* Assert that malloc() has not failed */
  assert( !sqlite3MallocFailed() );

  assert( ppStmt );
  *ppStmt = 0;
  if( sqlite3SafetyOn(db) ){
    return SQLITE_MISUSE;
  }

  /* If any attached database schemas are locked, do not proceed with
  ** compilation. Instead return SQLITE_LOCKED immediately.
  */
  for(i=0; i<db->nDb; i++) {
    Btree *pBt = db->aDb[i].pBt;
    if( pBt && sqlite3BtreeSchemaLocked(pBt) ){
      const char *zDb = db->aDb[i].zName;
      sqlite3Error(db, SQLITE_LOCKED, "database schema is locked: %s", zDb);
      sqlite3SafetyOff(db);
      return SQLITE_LOCKED;
    }
  }
  
  memset(&sParse, 0, sizeof(sParse));
  sParse.db = db;
  if( nBytes>=0 && zSql[nBytes]!=0 ){
    char *zSqlCopy = sqlite3StrNDup(zSql, nBytes);
    sqlite3RunParser(&sParse, zSqlCopy, &zErrMsg);
    sParse.zTail += zSql - zSqlCopy;
    sqliteFree(zSqlCopy);
  }else{
    sqlite3RunParser(&sParse, zSql, &zErrMsg);
  }

  if( sqlite3MallocFailed() ){
    sParse.rc = SQLITE_NOMEM;
  }
  if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK;
  if( sParse.checkSchema && !schemaIsValid(db) ){
    sParse.rc = SQLITE_SCHEMA;
  }
  if( sParse.rc==SQLITE_SCHEMA ){
    sqlite3ResetInternalSchema(db, 0);
  }
  if( pzTail ) *pzTail = sParse.zTail;
  rc = sParse.rc;

#ifndef SQLITE_OMIT_EXPLAIN
  if( rc==SQLITE_OK && sParse.pVdbe && sParse.explain ){
    if( sParse.explain==2 ){
      sqlite3VdbeSetNumCols(sParse.pVdbe, 3);
      sqlite3VdbeSetColName(sParse.pVdbe, 0, COLNAME_NAME, "order", P3_STATIC);
      sqlite3VdbeSetColName(sParse.pVdbe, 1, COLNAME_NAME, "from", P3_STATIC);
      sqlite3VdbeSetColName(sParse.pVdbe, 2, COLNAME_NAME, "detail", P3_STATIC);
    }else{
      sqlite3VdbeSetNumCols(sParse.pVdbe, 5);
      sqlite3VdbeSetColName(sParse.pVdbe, 0, COLNAME_NAME, "addr", P3_STATIC);
      sqlite3VdbeSetColName(sParse.pVdbe, 1, COLNAME_NAME, "opcode", P3_STATIC);
      sqlite3VdbeSetColName(sParse.pVdbe, 2, COLNAME_NAME, "p1", P3_STATIC);
      sqlite3VdbeSetColName(sParse.pVdbe, 3, COLNAME_NAME, "p2", P3_STATIC);
      sqlite3VdbeSetColName(sParse.pVdbe, 4, COLNAME_NAME, "p3", P3_STATIC);
    }
  } 
#endif

  if( sqlite3SafetyOff(db) ){
    rc = SQLITE_MISUSE;
  }
  if( rc==SQLITE_OK ){
    *ppStmt = (sqlite3_stmt*)sParse.pVdbe;
  }else if( sParse.pVdbe ){
    sqlite3_finalize((sqlite3_stmt*)sParse.pVdbe);
  }

  if( zErrMsg ){
    sqlite3Error(db, rc, "%s", zErrMsg);
    sqliteFree(zErrMsg);
  }else{
    sqlite3Error(db, rc, 0);
  }

  rc = sqlite3ApiExit(db, rc);
  sqlite3ReleaseThreadData();
  return rc;
}
예제 #4
0
파일: legacy.c 프로젝트: wangjufan/sqlite
/*
** Execute SQL code.
** Return one of the SQLITE_ success/failure codes.
** Also write an error message into memory obtained from malloc() and make *pzErrMsg point to that message.
**
** If the SQL is a query, then for each row in the query result the xCallback() function is called.
** pArg becomes the first argument to xCallback().
** If xCallback=NULL then no callback is invoked, even for queries.
*/
int sqlite3_exec(
  sqlite3 *db,                /* The database on which the SQL executes */
  const char *zSql,            /* The SQL to be executed */
  sqlite3_callback xCallback,    /* Invoke this callback routine */
  void *pArg,                 /* First argument to xCallback() */
  char **pzErrMsg             /* Write error messages here */
){
  int rc = SQLITE_OK;         /* Return code */
  const char *zLeftover;      /* Tail of unprocessed SQL */
  sqlite3_stmt *pStmt = 0;    /* The current SQL statement */
  char **azCols = 0;          /* Names of result columns */
  int callbackIsInit;         /* True if callback data is initialized */

  if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
  if( zSql==0 ) zSql = "";

  sqlite3_mutex_enter(db->mutex);
  sqlite3Error(db, SQLITE_OK);
  while( rc==SQLITE_OK && zSql[0] ){
    int nCol;
    char **azVals = 0;

    pStmt = 0;
    rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover);
    assert( rc==SQLITE_OK || pStmt==0 );
    if( rc!=SQLITE_OK ){
      continue;
    }
    if( !pStmt ){
      /* this happens for a comment or white-space */
      zSql = zLeftover;
      continue;
    }

    callbackIsInit = 0;
    nCol = sqlite3_column_count(pStmt);

    while( 1 ){
      int i;
      rc = sqlite3_step(pStmt);

      /* Invoke the callback function if required */
      if( xCallback && (SQLITE_ROW==rc || 
          (SQLITE_DONE==rc
            && !callbackIsInit
            && db->flags&SQLITE_NullCallback)) ){
        if( !callbackIsInit ){
          azCols = sqlite3DbMallocRaw(db, (2*nCol+1)*sizeof(const char*));
          if( azCols==0 ){
            goto exec_out;
          }
          for(i=0; i<nCol; i++){
            azCols[i] = (char *)sqlite3_column_name(pStmt, i);
            /* sqlite3VdbeSetColName() installs column names as UTF8
            ** strings so there is no way for sqlite3_column_name() to fail. */
            assert( azCols[i]!=0 );
          }
          callbackIsInit = 1;
        }
        if( rc==SQLITE_ROW ){
          azVals = &azCols[nCol];
          for(i=0; i<nCol; i++){
            azVals[i] = (char *)sqlite3_column_text(pStmt, i);
            if( !azVals[i] && sqlite3_column_type(pStmt, i)!=SQLITE_NULL ){
              sqlite3OomFault(db);
              goto exec_out;
            }
          }
          azVals[i] = 0;
        }
        if( xCallback(pArg, nCol, azVals, azCols) ){
          /* EVIDENCE-OF: R-38229-40159 If the callback function to
          ** sqlite3_exec() returns non-zero, then sqlite3_exec() will
          ** return SQLITE_ABORT. */
          rc = SQLITE_ABORT;
          sqlite3VdbeFinalize((Vdbe *)pStmt);
          pStmt = 0;
          sqlite3Error(db, SQLITE_ABORT);
          goto exec_out;
        }
      }

      if( rc!=SQLITE_ROW ){
        rc = sqlite3VdbeFinalize((Vdbe *)pStmt);
        pStmt = 0;
        zSql = zLeftover;
        while( sqlite3Isspace(zSql[0]) ) zSql++;
        break;
      }
    }

    sqlite3DbFree(db, azCols);
    azCols = 0;
  }

exec_out:
  if( pStmt ) sqlite3VdbeFinalize((Vdbe *)pStmt);
  sqlite3DbFree(db, azCols);

  rc = sqlite3ApiExit(db, rc);
  if( rc!=SQLITE_OK && pzErrMsg ){
    *pzErrMsg = sqlite3DbStrDup(0, sqlite3_errmsg(db));
    if( *pzErrMsg==0 ){
      rc = SQLITE_NOMEM_BKPT;
      sqlite3Error(db, SQLITE_NOMEM);
    }
  }else if( pzErrMsg ){
    *pzErrMsg = 0;
  }

  assert( (rc&db->errMask)==rc );
  sqlite3_mutex_leave(db->mutex);
  return rc;
}
예제 #5
0
파일: main.c 프로젝트: bluebellzhy/chromium
/*
** Create a new collating function for database "db".  The name is zName
** and the encoding is enc.
*/
static int createCollation(
  sqlite3* db, 
  const char *zName, 
  int enc, 
  void* pCtx,
  int(*xCompare)(void*,int,const void*,int,const void*),
  void(*xDel)(void*)
){
  CollSeq *pColl;
  int enc2;
  
  if( sqlite3SafetyCheck(db) ){
    return SQLITE_MISUSE;
  }

  /* If SQLITE_UTF16 is specified as the encoding type, transform this
  ** to one of SQLITE_UTF16LE or SQLITE_UTF16BE using the
  ** SQLITE_UTF16NATIVE macro. SQLITE_UTF16 is not used internally.
  */
  enc2 = enc & ~SQLITE_UTF16_ALIGNED;
  if( enc2==SQLITE_UTF16 ){
    enc2 = SQLITE_UTF16NATIVE;
  }

  if( (enc2&~3)!=0 ){
    sqlite3Error(db, SQLITE_ERROR, "unknown encoding");
    return SQLITE_ERROR;
  }

  /* Check if this call is removing or replacing an existing collation 
  ** sequence. If so, and there are active VMs, return busy. If there
  ** are no active VMs, invalidate any pre-compiled statements.
  */
  pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, strlen(zName), 0);
  if( pColl && pColl->xCmp ){
    if( db->activeVdbeCnt ){
      sqlite3Error(db, SQLITE_BUSY, 
        "Unable to delete/modify collation sequence due to active statements");
      return SQLITE_BUSY;
    }
    sqlite3ExpirePreparedStatements(db);

    /* If collation sequence pColl was created directly by a call to
    ** sqlite3_create_collation, and not generated by synthCollSeq(),
    ** then any copies made by synthCollSeq() need to be invalidated.
    ** Also, collation destructor - CollSeq.xDel() - function may need
    ** to be called.
    */ 
    if( (pColl->enc & ~SQLITE_UTF16_ALIGNED)==enc2 ){
      CollSeq *aColl = sqlite3HashFind(&db->aCollSeq, zName, strlen(zName));
      int j;
      for(j=0; j<3; j++){
        CollSeq *p = &aColl[j];
        if( p->enc==pColl->enc ){
          if( p->xDel ){
            p->xDel(p->pUser);
          }
          p->xCmp = 0;
        }
      }
    }
  }

  pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, strlen(zName), 1);
  if( pColl ){
    pColl->xCmp = xCompare;
    pColl->pUser = pCtx;
    pColl->xDel = xDel;
    pColl->enc = enc2 | (enc & SQLITE_UTF16_ALIGNED);
  }
  sqlite3Error(db, SQLITE_OK, 0);
  return SQLITE_OK;
}
예제 #6
0
파일: main.c 프로젝트: bluebellzhy/chromium
/*
** This routine does the work of opening a database on behalf of
** sqlite3_open() and sqlite3_open16(). The database filename "zFilename"  
** is UTF-8 encoded.
*/
static int openDatabase(
  const char *zFilename, /* Database filename UTF-8 encoded */
  sqlite3 **ppDb         /* OUT: Returned database handle */
){
  sqlite3 *db;
  int rc;
  CollSeq *pColl;

  assert( !sqlite3MallocFailed() );

  /* Allocate the sqlite data structure */
  db = sqliteMalloc( sizeof(sqlite3) );
  if( db==0 ) goto opendb_out;
  db->errMask = 0xff;
  db->priorNewRowid = 0;
  db->magic = SQLITE_MAGIC_BUSY;
  db->nDb = 2;
  db->aDb = db->aDbStatic;
  db->autoCommit = 1;
  db->flags |= SQLITE_ShortColNames
#if SQLITE_DEFAULT_FILE_FORMAT<4
                 | SQLITE_LegacyFileFmt
#endif
#ifdef SQLITE_ENABLE_LOAD_EXTENSION
                 | SQLITE_LoadExtension
#endif
      ;
  sqlite3HashInit(&db->aFunc, SQLITE_HASH_STRING, 0);
  sqlite3HashInit(&db->aCollSeq, SQLITE_HASH_STRING, 0);
#ifndef SQLITE_OMIT_VIRTUALTABLE
  sqlite3HashInit(&db->aModule, SQLITE_HASH_STRING, 0);
#endif

  /* Add the default collation sequence BINARY. BINARY works for both UTF-8
  ** and UTF-16, so add a version for each to avoid any unnecessary
  ** conversions. The only error that can occur here is a malloc() failure.
  */
  if( createCollation(db, "BINARY", SQLITE_UTF8, 0, binCollFunc, 0) ||
      createCollation(db, "BINARY", SQLITE_UTF16BE, 0, binCollFunc, 0) ||
      createCollation(db, "BINARY", SQLITE_UTF16LE, 0, binCollFunc, 0) ||
      (db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 6, 0))==0 
  ){
    assert( sqlite3MallocFailed() );
    db->magic = SQLITE_MAGIC_CLOSED;
    goto opendb_out;
  }

  /* Also add a UTF-8 case-insensitive collation sequence. */
  createCollation(db, "NOCASE", SQLITE_UTF8, 0, nocaseCollatingFunc, 0);

  /* Set flags on the built-in collating sequences */
  db->pDfltColl->type = SQLITE_COLL_BINARY;
  pColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "NOCASE", 6, 0);
  if( pColl ){
    pColl->type = SQLITE_COLL_NOCASE;
  }

  /* Open the backend database driver */
  rc = sqlite3BtreeFactory(db, zFilename, 0, SQLITE_DEFAULT_CACHE_SIZE,
                           &db->aDb[0].pBt);
  if( rc!=SQLITE_OK ){
    sqlite3Error(db, rc, 0);
    db->magic = SQLITE_MAGIC_CLOSED;
    goto opendb_out;
  }
  db->aDb[0].pSchema = sqlite3SchemaGet(db->aDb[0].pBt);
  db->aDb[1].pSchema = sqlite3SchemaGet(0);


  /* The default safety_level for the main database is 'full'; for the temp
  ** database it is 'NONE'. This matches the pager layer defaults.  
  */
  db->aDb[0].zName = "main";
  db->aDb[0].safety_level = 3;
#ifndef SQLITE_OMIT_TEMPDB
  db->aDb[1].zName = "temp";
  db->aDb[1].safety_level = 1;
#endif

  db->magic = SQLITE_MAGIC_OPEN;
  if( sqlite3MallocFailed() ){
    goto opendb_out;
  }

  /* Register all built-in functions, but do not attempt to read the
  ** database schema yet. This is delayed until the first time the database
  ** is accessed.
  */
  sqlite3Error(db, SQLITE_OK, 0);
  sqlite3RegisterBuiltinFunctions(db);

  /* Load automatic extensions - extensions that have been registered
  ** using the sqlite3_automatic_extension() API.
  */
  (void)sqlite3AutoLoadExtensions(db);
  if( sqlite3_errcode(db)!=SQLITE_OK ){
    goto opendb_out;
  }

#ifdef SQLITE_ENABLE_FTS1
  if( !sqlite3MallocFailed() ){
    extern int sqlite3Fts1Init(sqlite3*);
    rc = sqlite3Fts1Init(db);
  }
#endif

#ifdef SQLITE_ENABLE_FTS2
  if( !sqlite3MallocFailed() && rc==SQLITE_OK ){
    extern int sqlite3Fts2Init(sqlite3*);
    rc = sqlite3Fts2Init(db);
  }
#endif

#ifdef SQLITE_ENABLE_ICU
  if( !sqlite3MallocFailed() && rc==SQLITE_OK ){
    extern int sqlite3IcuInit(sqlite3*);
    rc = sqlite3IcuInit(db);
  }
#endif
  sqlite3Error(db, rc, 0);

  /* -DSQLITE_DEFAULT_LOCKING_MODE=1 makes EXCLUSIVE the default locking
  ** mode.  -DSQLITE_DEFAULT_LOCKING_MODE=0 make NORMAL the default locking
  ** mode.  Doing nothing at all also makes NORMAL the default.
  */
#ifdef SQLITE_DEFAULT_LOCKING_MODE
  db->dfltLockMode = SQLITE_DEFAULT_LOCKING_MODE;
  sqlite3PagerLockingMode(sqlite3BtreePager(db->aDb[0].pBt),
                          SQLITE_DEFAULT_LOCKING_MODE);
#endif

opendb_out:
  if( SQLITE_NOMEM==(rc = sqlite3_errcode(db)) ){
    sqlite3_close(db);
    db = 0;
  }
  *ppDb = db;
  return sqlite3ApiExit(0, rc);
}
예제 #7
0
파일: main.c 프로젝트: bluebellzhy/chromium
int sqlite3_table_column_metadata(
  sqlite3 *db,                /* Connection handle */
  const char *zDbName,        /* Database name or NULL */
  const char *zTableName,     /* Table name */
  const char *zColumnName,    /* Column name */
  char const **pzDataType,    /* OUTPUT: Declared data type */
  char const **pzCollSeq,     /* OUTPUT: Collation sequence name */
  int *pNotNull,              /* OUTPUT: True if NOT NULL constraint exists */
  int *pPrimaryKey,           /* OUTPUT: True if column part of PK */
  int *pAutoinc               /* OUTPUT: True if colums is auto-increment */
){
  int rc;
  char *zErrMsg = 0;
  Table *pTab = 0;
  Column *pCol = 0;
  int iCol;

  char const *zDataType = 0;
  char const *zCollSeq = 0;
  int notnull = 0;
  int primarykey = 0;
  int autoinc = 0;

  /* Ensure the database schema has been loaded */
  if( sqlite3SafetyOn(db) ){
    return SQLITE_MISUSE;
  }
  rc = sqlite3Init(db, &zErrMsg);
  if( SQLITE_OK!=rc ){
    goto error_out;
  }

  /* Locate the table in question */
  pTab = sqlite3FindTable(db, zTableName, zDbName);
  if( !pTab || pTab->pSelect ){
    pTab = 0;
    goto error_out;
  }

  /* Find the column for which info is requested */
  if( sqlite3IsRowid(zColumnName) ){
    iCol = pTab->iPKey;
    if( iCol>=0 ){
      pCol = &pTab->aCol[iCol];
    }
  }else{
    for(iCol=0; iCol<pTab->nCol; iCol++){
      pCol = &pTab->aCol[iCol];
      if( 0==sqlite3StrICmp(pCol->zName, zColumnName) ){
        break;
      }
    }
    if( iCol==pTab->nCol ){
      pTab = 0;
      goto error_out;
    }
  }

  /* The following block stores the meta information that will be returned
  ** to the caller in local variables zDataType, zCollSeq, notnull, primarykey
  ** and autoinc. At this point there are two possibilities:
  ** 
  **     1. The specified column name was rowid", "oid" or "_rowid_" 
  **        and there is no explicitly declared IPK column. 
  **
  **     2. The table is not a view and the column name identified an 
  **        explicitly declared column. Copy meta information from *pCol.
  */ 
  if( pCol ){
    zDataType = pCol->zType;
    zCollSeq = pCol->zColl;
    notnull = (pCol->notNull?1:0);
    primarykey  = (pCol->isPrimKey?1:0);
    autoinc = ((pTab->iPKey==iCol && pTab->autoInc)?1:0);
  }else{
    zDataType = "INTEGER";
    primarykey = 1;
  }
  if( !zCollSeq ){
    zCollSeq = "BINARY";
  }

error_out:
  if( sqlite3SafetyOff(db) ){
    rc = SQLITE_MISUSE;
  }

  /* Whether the function call succeeded or failed, set the output parameters
  ** to whatever their local counterparts contain. If an error did occur,
  ** this has the effect of zeroing all output parameters.
  */
  if( pzDataType ) *pzDataType = zDataType;
  if( pzCollSeq ) *pzCollSeq = zCollSeq;
  if( pNotNull ) *pNotNull = notnull;
  if( pPrimaryKey ) *pPrimaryKey = primarykey;
  if( pAutoinc ) *pAutoinc = autoinc;

  if( SQLITE_OK==rc && !pTab ){
    sqlite3SetString(&zErrMsg, "no such table column: ", zTableName, ".", 
        zColumnName, 0);
    rc = SQLITE_ERROR;
  }
  sqlite3Error(db, rc, (zErrMsg?"%s":0), zErrMsg);
  sqliteFree(zErrMsg);
  return sqlite3ApiExit(db, rc);
}
예제 #8
0
파일: main.c 프로젝트: bluebellzhy/chromium
/*
** This function is exactly the same as sqlite3_create_function(), except
** that it is designed to be called by internal code. The difference is
** that if a malloc() fails in sqlite3_create_function(), an error code
** is returned and the mallocFailed flag cleared. 
*/
int sqlite3CreateFunc(
  sqlite3 *db,
  const char *zFunctionName,
  int nArg,
  int enc,
  void *pUserData,
  void (*xFunc)(sqlite3_context*,int,sqlite3_value **),
  void (*xStep)(sqlite3_context*,int,sqlite3_value **),
  void (*xFinal)(sqlite3_context*)
){
  FuncDef *p;
  int nName;

  if( sqlite3SafetyCheck(db) ){
    return SQLITE_MISUSE;
  }
  if( zFunctionName==0 ||
      (xFunc && (xFinal || xStep)) || 
      (!xFunc && (xFinal && !xStep)) ||
      (!xFunc && (!xFinal && xStep)) ||
      (nArg<-1 || nArg>127) ||
      (255<(nName = strlen(zFunctionName))) ){
    sqlite3Error(db, SQLITE_ERROR, "bad parameters");
    return SQLITE_ERROR;
  }
  
#ifndef SQLITE_OMIT_UTF16
  /* If SQLITE_UTF16 is specified as the encoding type, transform this
  ** to one of SQLITE_UTF16LE or SQLITE_UTF16BE using the
  ** SQLITE_UTF16NATIVE macro. SQLITE_UTF16 is not used internally.
  **
  ** If SQLITE_ANY is specified, add three versions of the function
  ** to the hash table.
  */
  if( enc==SQLITE_UTF16 ){
    enc = SQLITE_UTF16NATIVE;
  }else if( enc==SQLITE_ANY ){
    int rc;
    rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF8,
         pUserData, xFunc, xStep, xFinal);
    if( rc!=SQLITE_OK ) return rc;
    rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF16LE,
        pUserData, xFunc, xStep, xFinal);
    if( rc!=SQLITE_OK ) return rc;
    enc = SQLITE_UTF16BE;
  }
#else
  enc = SQLITE_UTF8;
#endif
  
  /* Check if an existing function is being overridden or deleted. If so,
  ** and there are active VMs, then return SQLITE_BUSY. If a function
  ** is being overridden/deleted but there are no active VMs, allow the
  ** operation to continue but invalidate all precompiled statements.
  */
  p = sqlite3FindFunction(db, zFunctionName, nName, nArg, enc, 0);
  if( p && p->iPrefEnc==enc && p->nArg==nArg ){
    if( db->activeVdbeCnt ){
      sqlite3Error(db, SQLITE_BUSY, 
        "Unable to delete/modify user-function due to active statements");
      assert( !sqlite3MallocFailed() );
      return SQLITE_BUSY;
    }else{
      sqlite3ExpirePreparedStatements(db);
    }
  }

  p = sqlite3FindFunction(db, zFunctionName, nName, nArg, enc, 1);
  if( p ){
    p->flags = 0;
    p->xFunc = xFunc;
    p->xStep = xStep;
    p->xFinalize = xFinal;
    p->pUserData = pUserData;
    p->nArg = nArg;
  }
  return SQLITE_OK;
}
예제 #9
0
파일: main.c 프로젝트: bluebellzhy/chromium
/*
** Close an existing SQLite database
*/
int sqlite3_close(sqlite3 *db){
  HashElem *i;
  int j;

  if( !db ){
    return SQLITE_OK;
  }
  if( sqlite3SafetyCheck(db) ){
    return SQLITE_MISUSE;
  }

#ifdef SQLITE_SSE
  {
    extern void sqlite3SseCleanup(sqlite3*);
    sqlite3SseCleanup(db);
  }
#endif 

  sqlite3ResetInternalSchema(db, 0);

  /* If a transaction is open, the ResetInternalSchema() call above
  ** will not have called the xDisconnect() method on any virtual
  ** tables in the db->aVTrans[] array. The following sqlite3VtabRollback()
  ** call will do so. We need to do this before the check for active
  ** SQL statements below, as the v-table implementation may be storing
  ** some prepared statements internally.
  */
  sqlite3VtabRollback(db);

  /* If there are any outstanding VMs, return SQLITE_BUSY. */
  if( db->pVdbe ){
    sqlite3Error(db, SQLITE_BUSY, 
        "Unable to close due to unfinalised statements");
    return SQLITE_BUSY;
  }
  assert( !sqlite3SafetyCheck(db) );

  /* FIX ME: db->magic may be set to SQLITE_MAGIC_CLOSED if the database
  ** cannot be opened for some reason. So this routine needs to run in
  ** that case. But maybe there should be an extra magic value for the
  ** "failed to open" state.
  **
  ** TODO: Coverage tests do not test the case where this condition is
  ** true. It's hard to see how to cause it without messing with threads.
  */
  if( db->magic!=SQLITE_MAGIC_CLOSED && sqlite3SafetyOn(db) ){
    /* printf("DID NOT CLOSE\n"); fflush(stdout); */
    return SQLITE_ERROR;
  }

  for(j=0; j<db->nDb; j++){
    struct Db *pDb = &db->aDb[j];
    if( pDb->pBt ){
      sqlite3BtreeClose(pDb->pBt);
      pDb->pBt = 0;
      if( j!=1 ){
        pDb->pSchema = 0;
      }
    }
  }
  sqlite3ResetInternalSchema(db, 0);
  assert( db->nDb<=2 );
  assert( db->aDb==db->aDbStatic );
  for(i=sqliteHashFirst(&db->aFunc); i; i=sqliteHashNext(i)){
    FuncDef *pFunc, *pNext;
    for(pFunc = (FuncDef*)sqliteHashData(i); pFunc; pFunc=pNext){
      pNext = pFunc->pNext;
      sqliteFree(pFunc);
    }
  }

  for(i=sqliteHashFirst(&db->aCollSeq); i; i=sqliteHashNext(i)){
    CollSeq *pColl = (CollSeq *)sqliteHashData(i);
    /* Invoke any destructors registered for collation sequence user data. */
    for(j=0; j<3; j++){
      if( pColl[j].xDel ){
        pColl[j].xDel(pColl[j].pUser);
      }
    }
    sqliteFree(pColl);
  }
  sqlite3HashClear(&db->aCollSeq);
#ifndef SQLITE_OMIT_VIRTUALTABLE
  for(i=sqliteHashFirst(&db->aModule); i; i=sqliteHashNext(i)){
    Module *pMod = (Module *)sqliteHashData(i);
    if( pMod->xDestroy ){
      pMod->xDestroy(pMod->pAux);
    }
    sqliteFree(pMod);
  }
  sqlite3HashClear(&db->aModule);
#endif

  sqlite3HashClear(&db->aFunc);
  sqlite3Error(db, SQLITE_OK, 0); /* Deallocates any cached error strings. */
  if( db->pErr ){
    sqlite3ValueFree(db->pErr);
  }
  sqlite3CloseExtensions(db);

  db->magic = SQLITE_MAGIC_ERROR;

  /* The temp-database schema is allocated differently from the other schema
  ** objects (using sqliteMalloc() directly, instead of sqlite3BtreeSchema()).
  ** So it needs to be freed here. Todo: Why not roll the temp schema into
  ** the same sqliteMalloc() as the one that allocates the database 
  ** structure?
  */
  sqliteFree(db->aDb[1].pSchema);
  sqliteFree(db);
  sqlite3ReleaseThreadData();
  return SQLITE_OK;
}
예제 #10
0
/*
** Execute the statement pStmt, either until a row of data is ready, the
** statement is completely executed or an error occurs.
*/
int sqlite3_step(sqlite3_stmt *pStmt){
  Vdbe *p = (Vdbe*)pStmt;
  sqlite3 *db;
  int rc;

  /* Assert that malloc() has not failed */
  assert( !sqlite3MallocFailed() );

  if( p==0 || p->magic!=VDBE_MAGIC_RUN ){
    return SQLITE_MISUSE;
  }
  if( p->aborted ){
    return SQLITE_ABORT;
  }
  if( p->pc<=0 && p->expired ){
    if( p->rc==SQLITE_OK ){
      p->rc = SQLITE_SCHEMA;
    }
    return SQLITE_ERROR;
  }
  db = p->db;
  if( sqlite3SafetyOn(db) ){
    p->rc = SQLITE_MISUSE;
    return SQLITE_MISUSE;
  }
  if( p->pc<0 ){
#ifndef SQLITE_OMIT_TRACE
    /* Invoke the trace callback if there is one
    */
    if( db->xTrace && !db->init.busy ){
      assert( p->nOp>0 );
      assert( p->aOp[p->nOp-1].opcode==OP_Noop );
      assert( p->aOp[p->nOp-1].p3!=0 );
      assert( p->aOp[p->nOp-1].p3type==P3_DYNAMIC );
      sqlite3SafetyOff(db);
      db->xTrace(db->pTraceArg, p->aOp[p->nOp-1].p3);
      if( sqlite3SafetyOn(db) ){
        p->rc = SQLITE_MISUSE;
        return SQLITE_MISUSE;
      }
    }
    if( db->xProfile && !db->init.busy ){
      double rNow;
      sqlite3OsCurrentTime(&rNow);
      p->startTime = (rNow - (int)rNow)*3600.0*24.0*1000000000.0;
    }
#endif

    /* Print a copy of SQL as it is executed if the SQL_TRACE pragma is turned
    ** on in debugging mode.
    */
#ifdef SQLITE_DEBUG
    if( (db->flags & SQLITE_SqlTrace)!=0 ){
      sqlite3DebugPrintf("SQL-trace: %s\n", p->aOp[p->nOp-1].p3);
    }
#endif /* SQLITE_DEBUG */

    db->activeVdbeCnt++;
    p->pc = 0;
  }
#ifndef SQLITE_OMIT_EXPLAIN
  if( p->explain ){
    rc = sqlite3VdbeList(p);
  }else
#endif /* SQLITE_OMIT_EXPLAIN */
  {
    rc = sqlite3VdbeExec(p);
  }

  if( sqlite3SafetyOff(db) ){
    rc = SQLITE_MISUSE;
  }

#ifndef SQLITE_OMIT_TRACE
  /* Invoke the profile callback if there is one
  */
  if( rc!=SQLITE_ROW && db->xProfile && !db->init.busy ){
    double rNow;
    u64 elapseTime;

    sqlite3OsCurrentTime(&rNow);
    elapseTime = (rNow - (int)rNow)*3600.0*24.0*1000000000.0 - p->startTime;
    assert( p->nOp>0 );
    assert( p->aOp[p->nOp-1].opcode==OP_Noop );
    assert( p->aOp[p->nOp-1].p3!=0 );
    assert( p->aOp[p->nOp-1].p3type==P3_DYNAMIC );
    db->xProfile(db->pProfileArg, p->aOp[p->nOp-1].p3, elapseTime);
  }
#endif

  sqlite3Error(p->db, rc, 0);
  p->rc = sqlite3ApiExit(p->db, p->rc);
  return rc;
}
예제 #11
0
/*
** Create an sqlite3_backup process to copy the contents of zSrcDb from
** connection handle pSrcDb to zDestDb in pDestDb. If successful, return
** a pointer to the new sqlite3_backup object.
**
** If an error occurs, NULL is returned and an error code and error message
** stored in database handle pDestDb.
*/
sqlite3_backup *sqlite3_backup_init(
  sqlite3* pDestDb,                     /* Database to write to */
  const char *zDestDb,                  /* Name of database within pDestDb */
  sqlite3* pSrcDb,                      /* Database connection to read from */
  const char *zSrcDb                    /* Name of database within pSrcDb */
){
  sqlite3_backup *p;                    /* Value to return */

#ifdef SQLITE_ENABLE_API_ARMOR
  if( !sqlite3SafetyCheckOk(pSrcDb)||!sqlite3SafetyCheckOk(pDestDb) ){
    (void)SQLITE_MISUSE_BKPT;
    return 0;
  }
#endif

  /* Lock the source database handle. The destination database
  ** handle is not locked in this routine, but it is locked in
  ** sqlite3_backup_step(). The user is required to ensure that no
  ** other thread accesses the destination handle for the duration
  ** of the backup operation.  Any attempt to use the destination
  ** database connection while a backup is in progress may cause
  ** a malfunction or a deadlock.
  */
  sqlite3_mutex_enter(pSrcDb->mutex);
  sqlite3_mutex_enter(pDestDb->mutex);

  if( pSrcDb==pDestDb ){
    sqlite3ErrorWithMsg(
        pDestDb, SQLITE_ERROR, "source and destination must be distinct"
    );
    p = 0;
  }else {
    /* Allocate space for a new sqlite3_backup object...
    ** EVIDENCE-OF: R-64852-21591 The sqlite3_backup object is created by a
    ** call to sqlite3_backup_init() and is destroyed by a call to
    ** sqlite3_backup_finish(). */
    p = (sqlite3_backup *)sqlite3MallocZero(sizeof(sqlite3_backup));
    if( !p ){
      sqlite3Error(pDestDb, SQLITE_NOMEM_BKPT);
    }
  }

  /* If the allocation succeeded, populate the new object. */
  if( p ){
    p->pSrc = findBtree(pDestDb, pSrcDb, zSrcDb);
    p->pDest = findBtree(pDestDb, pDestDb, zDestDb);
    p->pDestDb = pDestDb;
    p->pSrcDb = pSrcDb;
    p->iNext = 1;
    p->isAttached = 0;

    if( 0==p->pSrc || 0==p->pDest 
     || setDestPgsz(p)==SQLITE_NOMEM 
     || checkReadTransaction(pDestDb, p->pDest)!=SQLITE_OK 
     ){
      /* One (or both) of the named databases did not exist or an OOM
      ** error was hit. Or there is a transaction open on the destination
      ** database. The error has already been written into the pDestDb 
      ** handle. All that is left to do here is free the sqlite3_backup 
      ** structure.  */
      sqlite3_free(p);
      p = 0;
    }
  }
  if( p ){
    p->pSrc->nBackup++;
  }

  sqlite3_mutex_leave(pDestDb->mutex);
  sqlite3_mutex_leave(pSrcDb->mutex);
  return p;
}
예제 #12
0
파일: backup.c 프로젝트: CompassHXM/h-store
/*
** Copy nPage pages from the source b-tree to the destination.
*/
int sqlite3_backup_step(sqlite3_backup *p, int nPage) {
	int returnCode, pages;
	Parse parse;
	DB_ENV *dbenv;
	BtShared *pBtDest, *pBtSrc;

	pBtDest = pBtSrc = NULL;

	if (p->rc != SQLITE_OK || nPage == 0)
		return p->rc;

	sqlite3_mutex_enter(p->pSrcDb->mutex);
	sqlite3_mutex_enter(p->pDestDb->mutex);

	/*
	 * Make sure the schema has been read in, so the keyInfo
	 * can be retrieved for the indexes.  No-op if already read.
	 * If the schema has not been read then an update must have
	 * changed it, so backup will restart.
	 */
	memset(&parse, 0, sizeof(parse));
	parse.db = p->pSrcDb;
	p->rc = sqlite3ReadSchema(&parse);
	if (p->rc != SQLITE_OK)
		goto err;

	/*
	 * This process updated the source database, so
	 * the backup process has to restart.
	 */
	if (p->pSrc->updateDuringBackup > p->lastUpdate) {
		p->rc = SQLITE_LOCKED;
		if ((p->rc = backupCleanup(p)) != SQLITE_OK)
			goto err;
		else
			backupReset(p);
	}

	pages = nPage;

	if (!p->cleaned) {
		const char *home;
		const char inmem[9] = ":memory:";
		int storage;

		pBtDest = p->pDest->pBt;
		storage = p->pDest->pBt->dbStorage;
		if (storage == DB_STORE_NAMED)
			p->openDest = 1;
		if (strcmp(p->destName, "temp") == 0)
			p->pDest->schema = NULL;
		else 
			p->pDestDb->aDb[p->iDb].pSchema = NULL;
			
		p->rc = btreeDeleteEnvironment(p->pDest, p->fullName, 1);
		if (storage == DB_STORE_INMEM && strcmp(p->destName, "temp")
		    != 0)
			home = inmem;
		else
			home = p->fullName;
		if (p->rc != SQLITE_BUSY)
			p->pDest = p->pDestDb->aDb[p->iDb].pBt = NULL;
		if (p->rc != SQLITE_OK)
			goto err;
		/*
		 * Call sqlite3OpenTempDatabase instead of
		 * sqlite3BtreeOpen, because sqlite3OpenTempDatabase
		 * automatically chooses the right flags before calling
		 * sqlite3BtreeOpen.
		 */
		if (strcmp(p->destName, "temp") == 0) {
			memset(&parse, 0, sizeof(parse));
			parse.db = p->pDestDb;
			p->rc = sqlite3OpenTempDatabase(&parse);
			p->pDest = p->pDestDb->aDb[p->iDb].pBt;
			if (p->pDest && p->iDb != 1)
				p->pDest->schema =
				    p->pDestDb->aDb[p->iDb].pSchema;
		} else {
			p->rc = sqlite3BtreeOpen(NULL, home, p->pDestDb,
			    &p->pDest, SQLITE_DEFAULT_CACHE_SIZE |
			    SQLITE_OPEN_MAIN_DB, p->pDestDb->openFlags);
			p->pDestDb->aDb[p->iDb].pBt = p->pDest;
			if (p->pDest) {
				p->pDestDb->aDb[p->iDb].pSchema = 
				    sqlite3SchemaGet(p->pDestDb, p->pDest);
				if (p->pDestDb->aDb[p->iDb].pSchema == NULL)
					p->rc = SQLITE_NOMEM;
			}
		}

		if (p->pDest)
			p->pDest->nBackup++;
#ifdef SQLITE_HAS_CODEC
		/*
		 * In the case of a temporary source database, use the
		 * encryption of the main database.
		 */
		if (strcmp(p->srcName, "temp") == 0) {
			 int iDb = sqlite3FindDbName(p->pSrcDb, "main");
			 pBtSrc = p->pSrcDb->aDb[iDb].pBt->pBt;
		} else
			 pBtSrc = p->pSrc->pBt;
		if (p->rc == SQLITE_OK) {
			if (p->iDb == 0)
				p->rc = sqlite3_key(p->pDestDb,
				    pBtSrc->encrypt_pwd,
				    pBtSrc->encrypt_pwd_len);
			else
				p->rc = sqlite3CodecAttach(p->pDestDb, p->iDb,
				    pBtSrc->encrypt_pwd,
				    pBtSrc->encrypt_pwd_len);
		}
#endif
		if (p->rc != SQLITE_OK)
			goto err;
		p->cleaned = 1;
	}

	/*
	 * Begin a transaction, unfortuantely the lock on
	 * the schema has to be released to allow the sqlite_master
	 * table to be cleared, which could allow another thread to
	 * alter it, however accessing the backup database during
	 * backup is already an illegal condition with undefined
	 * results.
	 */
	if (!sqlite3BtreeIsInTrans(p->pDest)) {
		if (!p->pDest->connected) {
			p->rc = btreeOpenEnvironment(p->pDest, 1);
			if (p->rc != SQLITE_OK)
				goto err;
		}
		if ((p->rc = btreeBeginTransInternal(p->pDest, 2))
			!= SQLITE_OK)
			goto err;
	}
	/* Only this process should be accessing the backup environment. */
	if (p->pDest->pBt->nRef > 1) {
		p->rc = SQLITE_BUSY;
		goto err;
	}

	/*
	 * Begin a transaction, a lock error or update could have caused
	 * it to be released in a previous call to step.
	 */
	if (!p->srcTxn) {
		dbenv = p->pSrc->pBt->dbenv;
		if ((p->rc = dberr2sqlite(dbenv->txn_begin(dbenv,
		    p->pSrc->family_txn, &p->srcTxn, 0), NULL)) != SQLITE_OK)
			goto err;
	}

	/*
	 * An update could have dropped or created a table, so recalculate
	 * the list of tables.
	 */
	if (!p->tables) {
		if ((p->rc = btreeGetPageCount(p->pSrc,
		    &p->tables, &p->nPagecount, p->srcTxn)) != SQLITE_OK) {
				sqlite3Error(p->pSrcDb, p->rc, 0);
				goto err;
		}
		p->nRemaining = p->nPagecount;
	}

	/* Copy the pages. */
	p->rc = btreeCopyPages(p, &pages);
	if (p->rc == SQLITE_DONE) {
		p->nRemaining = 0;
		sqlite3ResetOneSchema(p->pDestDb, p->iDb);
		memset(&parse, 0, sizeof(parse));
		parse.db = p->pDestDb;
		p->rc = sqlite3ReadSchema(&parse);
		if (p->rc == SQLITE_OK)
			p->rc = SQLITE_DONE;
	} else if (p->rc != SQLITE_OK)
		goto err;

	/*
	 * The number of pages left to copy is an estimate, so
	 * do not let the number go to zero unless we are really
	 * done.
	 */
	if (p->rc != SQLITE_DONE) {
		if ((u32)pages >= p->nRemaining)
			p->nRemaining = 1;
		else
			p->nRemaining -= pages;
	}

err:	/*
	 * This process updated the source database, so
	 * the backup process has to restart.
	 */
	if (p->pSrc->updateDuringBackup > p->lastUpdate &&
	    (p->rc == SQLITE_OK || p->rc == SQLITE_DONE)) {
		int cleanCode;
		returnCode = p->rc;
		p->rc = SQLITE_LOCKED;
		if ((cleanCode = backupCleanup(p)) != SQLITE_OK)
			returnCode = p->rc = cleanCode;
		else
			backupReset(p);
	} else {
		returnCode = backupCleanup(p);
		if (returnCode == SQLITE_OK ||
		    (p->rc != SQLITE_OK && p->rc != SQLITE_DONE))
			returnCode = p->rc;
		else
			p->rc = returnCode;
	}
	/*
	 * On a locked or busy error the backup process is rolled back,
	 * but can be restarted by the user.
	 */
	if ( returnCode == SQLITE_LOCKED || returnCode == SQLITE_BUSY )
		backupReset(p);
	else if ( returnCode != SQLITE_OK && returnCode != SQLITE_DONE ) {
		sqlite3Error(p->pDestDb, p->rc, 0);
	}
	sqlite3_mutex_leave(p->pDestDb->mutex);
	sqlite3_mutex_leave(p->pSrcDb->mutex);
	return (returnCode);
}
예제 #13
0
파일: backup.c 프로젝트: CompassHXM/h-store
/*
** Create an sqlite3_backup process to copy the contents of zSrcDb from
** connection handle pSrcDb to zDestDb in pDestDb. If successful, return
** a pointer to the new sqlite3_backup object.
**
** If an error occurs, NULL is returned and an error code and error message
** stored in database handle pDestDb.
** pDestDb  Database to write to
** zDestDb  Name of database within pDestDb
** pSrcDb   Database connection to read from
** zSrcDb   Name of database within pSrcDb
*/
sqlite3_backup *sqlite3_backup_init(sqlite3* pDestDb, const char *zDestDb,
    sqlite3* pSrcDb, const char *zSrcDb)
{
	sqlite3_backup *p;                    /* Value to return */
	Parse parse;
	DB_ENV *dbenv;
	int ret;

	p = NULL;
	ret = 0;

	if (!pDestDb || !pSrcDb)
		return 0;

	sqlite3_mutex_enter(pSrcDb->mutex);
	sqlite3_mutex_enter(pDestDb->mutex);
	if (pSrcDb == pDestDb) {
		sqlite3Error(pDestDb, SQLITE_ERROR,
		    "source and destination must be distinct");
		goto err;
	}

	/* Allocate space for a new sqlite3_backup object */
	p = (sqlite3_backup *)sqlite3_malloc(sizeof(sqlite3_backup));
	if (!p) {
		sqlite3Error(pDestDb, SQLITE_NOMEM, 0);
		goto err;
	}

	memset(p, 0, sizeof(sqlite3_backup));
	p->pSrc = findBtree(pDestDb, pSrcDb, zSrcDb);
	p->pDest = findBtree(pDestDb, pDestDb, zDestDb);
	p->pDestDb = pDestDb;
	p->pSrcDb = pSrcDb;

	if (0 == p->pSrc) {
		p->rc = p->pSrcDb->errCode;
		goto err;
	}
	if (0 == p->pDest) {
		p->rc = p->pDestDb->errCode;
		goto err;
	}

	p->iDb = sqlite3FindDbName(pDestDb, zDestDb);

	p->srcName = sqlite3_malloc((int)strlen(zSrcDb) + 1);
	p->destName = sqlite3_malloc((int)strlen(zDestDb) + 1);
	if (0 == p->srcName || 0 == p->destName) {
		p->rc = SQLITE_NOMEM;
		goto err;
	}
	strncpy(p->srcName, zSrcDb, strlen(zSrcDb) + 1);
	strncpy(p->destName, zDestDb, strlen(zDestDb) + 1);

	if (p->pDest->pBt->full_name) {
		const char *fullName = p->pDest->pBt->full_name;
		p->fullName = sqlite3_malloc((int)strlen(fullName) + 1);
		if (!p->fullName) {
			p->rc = SQLITE_NOMEM;
			goto err;
		}
		strncpy(p->fullName, fullName, strlen(fullName) + 1);
	}

	/*
	 * Make sure the schema has been read in, so the keyInfo
	 * can be retrieved for the indexes.  No-op if already read.
	 */
	memset(&parse, 0, sizeof(parse));
	parse.db = p->pSrcDb;
	p->rc = sqlite3ReadSchema(&parse);
	if (p->rc != SQLITE_OK) {
		if (parse.zErrMsg != NULL)
			sqlite3DbFree(p->pSrcDb, parse.zErrMsg);
		goto err;
	}

	/* Begin a transaction on the source. */
	if (!p->pSrc->connected) {
		if ((p->rc = btreeOpenEnvironment(p->pSrc, 1)) != SQLITE_OK)
			goto err;
	}
	dbenv = p->pSrc->pBt->dbenv;
	p->rc = dberr2sqlite(dbenv->txn_begin(dbenv, p->pSrc->family_txn,
	    &p->srcTxn, 0), NULL);
	if (p->rc != SQLITE_OK) {
		sqlite3Error(pSrcDb, p->rc, 0);
		goto err;
	}

	/*
	 * Get the page count and list of tables to copy. This will
	 * result in a read lock on the schema table, held in the
	 * read transaction.
	 */
	if ((p->rc = btreeGetPageCount(p->pSrc,
	    &p->tables, &p->nPagecount, p->srcTxn)) != SQLITE_OK) {
		sqlite3Error(pSrcDb, p->rc, 0);
		goto err;
	}

	p->nRemaining = p->nPagecount;
	p->pSrc->nBackup++;
	p->pDest->nBackup++;
	p->lastUpdate = p->pSrc->updateDuringBackup;

	goto done;

err:	if (p != 0) {
		if (pDestDb->errCode == SQLITE_OK)
			sqlite3Error(pDestDb, p->rc, 0);
		if (p->srcTxn)
			p->srcTxn->abort(p->srcTxn);
		if (p->srcName != 0)
			sqlite3_free(p->srcName);
		if (p->destName != 0)
			sqlite3_free(p->destName);
		if (p->fullName != 0)
			sqlite3_free(p->fullName);
		if (p->tables != 0)
			sqlite3_free(p->tables);
		sqlite3_free(p);
		p = NULL;
	}
done:	sqlite3_mutex_leave(pDestDb->mutex);
	sqlite3_mutex_leave(pSrcDb->mutex);
	return p;
}