Beispiel #1
0
/*
** Check schema cookies in all databases.  If any cookie is out
** of date, return 0.  If all schema cookies are current, return 1.
*/
static int schemaIsValid(sqlite3 *db){
  int iDb;
  int rc;
  BtCursor *curTemp;
  int cookie;
  int allOk = 1;

  curTemp = (BtCursor *)sqlite3Malloc(sqlite3BtreeCursorSize());
  if( curTemp ){
    assert( sqlite3_mutex_held(db->mutex) );
    for(iDb=0; allOk && iDb<db->nDb; iDb++){
      Btree *pBt;
      pBt = db->aDb[iDb].pBt;
      if( pBt==0 ) continue;
      memset(curTemp, 0, sqlite3BtreeCursorSize());
      rc = sqlite3BtreeCursor(pBt, MASTER_ROOT, 0, 0, curTemp);
      if( rc==SQLITE_OK ){
        rc = sqlite3BtreeGetMeta(pBt, 1, (u32 *)&cookie);
        if( rc==SQLITE_OK && cookie!=db->aDb[iDb].pSchema->schema_cookie ){
          allOk = 0;
        }
        sqlite3BtreeCloseCursor(curTemp);
      }
      if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
        db->mallocFailed = 1;
      }
    }
    sqlite3_free(curTemp);
  }else{
    allOk = 0;
    db->mallocFailed = 1;
  }

  return allOk;
}
Beispiel #2
0
/*
** Usage:   btree_cursor ID TABLENUM WRITEABLE
**
** Create a new cursor.  Return the ID for the cursor.
*/
static int btree_cursor(
  void *NotUsed,
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  int argc,              /* Number of arguments */
  const char **argv      /* Text of each argument */
){
  Btree *pBt;
  int iTable;
  BtCursor *pCur;
  int rc;
  int wrFlag;
  char zBuf[30];

  if( argc!=4 ){
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
       " ID TABLENUM WRITEABLE\"", 0);
    return TCL_ERROR;
  }
  pBt = sqlite3TestTextToPtr(argv[1]);
  if( Tcl_GetInt(interp, argv[2], &iTable) ) return TCL_ERROR;
  if( Tcl_GetBoolean(interp, argv[3], &wrFlag) ) return TCL_ERROR;
  pCur = (BtCursor *)ckalloc(sqlite3BtreeCursorSize());
  memset(pCur, 0, sqlite3BtreeCursorSize());
  sqlite3BtreeEnter(pBt);
  rc = sqlite3BtreeCursor(pBt, iTable, wrFlag, 0, pCur);
  sqlite3BtreeLeave(pBt);
  if( rc ){
    ckfree((char *)pCur);
    Tcl_AppendResult(interp, errorName(rc), 0);
    return TCL_ERROR;
  }
  sqlite3_snprintf(sizeof(zBuf), zBuf,"%p", pCur);
  Tcl_AppendResult(interp, zBuf, 0);
  return SQLITE_OK;
}
Beispiel #3
0
/*
** Check schema cookies in all databases.  If any cookie is out
** of date, return 0.  If all schema cookies are current, return 1.
*/
static int schemaIsValid(sqlite3 *db){
  int iDb;
  int rc;
  BtCursor *curTemp;
  int cookie;
  int allOk = 1;

  for(iDb=0; allOk && iDb<db->nDb; iDb++){
    Btree *pBt;
    pBt = db->aDb[iDb].pBt;
    if( pBt==0 ) continue;
    rc = sqlite3BtreeCursor(pBt, MASTER_ROOT, 0, 0, 0, &curTemp);
    if( rc==SQLITE_OK ){
      rc = sqlite3BtreeGetMeta(pBt, 1, (u32 *)&cookie);
      if( rc==SQLITE_OK && cookie!=db->aDb[iDb].pSchema->schema_cookie ){
        allOk = 0;
      }
      sqlite3BtreeCloseCursor(curTemp);
    }
  }
  return allOk;
}
Beispiel #4
0
/*
 * Print statistics for tables and/or indexes using DB->stat_print()
 *
 * If msgfile is NULL, then statistics will be printed into stdout, otherwise
 * the statistics will be printed into the designated output stream.
 *
 * If name input is NULL, then statistics for all tables and indexes are
 * printed, otherwise only the statistics for that table or index is printed.
 *
 * Returns SQLITE_OK if there are no errors, -1 if an error occurred.
 */
SQLITE_API int bdbSqlDbStatPrint(sqlite3 *db, FILE *msgfile, char *name)
{
	BtCursor cur, *pCur = NULL;
	Btree *p;
	char **azResult = NULL;
	char *zErrMsg = NULL;
	char *zSql = NULL;
	DB *dbp;
	FILE *out;
	int i, rc, nRow, iTable, openTransaction = 0;

	if (!db || !db->aDb)
		return -1;

	p = db->aDb[0].pBt;
	assert(p);

	if (!(out = msgfile))
		out = stdout;

	/* Construct query to get root page number(s) */
	if (!name) {
		zSql = sqlite3_mprintf(
		    "SELECT type,name,rootpage FROM sqlite_master");
	}
	else {
		zSql = sqlite3_mprintf(
		    "SELECT type,name,rootpage FROM sqlite_master "
		    "WHERE name='%q'", name);
	}

	if (!zSql) {
		fprintf(stderr, "Error: memory allocation failed\n");
		goto err;
	}

	rc = sqlite3_get_table(db, zSql, &azResult, &nRow, 0, &zErrMsg);
	(void)sqlite3_free(zSql);

	if (zErrMsg) {
		fprintf(stderr, "Error: %s\n", zErrMsg);
		(void)sqlite3_free(zErrMsg);
		if (rc == SQLITE_OK)
			rc = -1;
		goto err;
	}
	else if (rc != SQLITE_OK) {
		fprintf(stderr, "Error: querying sqlite_master\n");
		goto err;
	}
	else if (nRow < 1)
		goto err;

	rc = sqlite3BtreeBeginTrans(p, 0);
	if (rc != SQLITE_OK) {
		fprintf(stderr, "Error: could not enter a transaction\n");
		goto err;
	}
	openTransaction = 1;

	/* Print stats for all tables in query's result */
	for (i = 1; i <= nRow; i++) {
		fprintf(out, "Statistics for %s \"%s\"\n",
		    azResult[3*i], azResult[3*i + 1]);
		iTable = atoi(azResult[3*i + 2]);

		pCur = &cur;
		(void)sqlite3BtreeCursorZero(pCur);

		/* Acquire a read cursor to retrieve the dbp for the table */
		rc = sqlite3BtreeCursor(p, iTable, 0, NULL, pCur);
		if (pCur->eState == CURSOR_FAULT)
			rc = pCur->error;
		if (rc != SQLITE_OK) {
			fprintf(stderr, "Error: could not create cursor\n");
			goto err;
		}

		assert(pCur->cached_db && pCur->cached_db->dbp);
		dbp = pCur->cached_db->dbp;
		(void)dbp->set_msgfile(dbp, out);
		(void)dbp->stat_print(dbp, DB_STAT_ALL);

		(void)sqlite3BtreeCloseCursor(&cur);
		pCur = NULL;
	}

err:
	if (pCur)
		(void)sqlite3BtreeCloseCursor(pCur);
	if (openTransaction)
		sqlite3BtreeCommit(p);
	if (azResult)
		(void)sqlite3_free_table(azResult);

	return rc;
}
Beispiel #5
0
/*
** Attempt to read the database schema and initialize internal
** data structures for a single database file.  The index of the
** database file is given by iDb.  iDb==0 is used for the main
** database.  iDb==1 should never be used.  iDb>=2 is used for
** auxiliary databases.  Return one of the SQLITE_ error codes to
** indicate success or failure.
*/
static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
  int rc;
  BtCursor *curMain;
  int size;
  Table *pTab;
  Db *pDb;
  char const *azArg[4];
  int meta[10];
  InitData initData;
  char const *zMasterSchema;
  char const *zMasterName = SCHEMA_TABLE(iDb);

  /*
  ** The master database table has a structure like this
  */
  static const char master_schema[] = 
     "CREATE TABLE sqlite_master(\n"
     "  type text,\n"
     "  name text,\n"
     "  tbl_name text,\n"
     "  rootpage integer,\n"
     "  sql text\n"
     ")"
  ;
#ifndef SQLITE_OMIT_TEMPDB
  static const char temp_master_schema[] = 
     "CREATE TEMP TABLE sqlite_temp_master(\n"
     "  type text,\n"
     "  name text,\n"
     "  tbl_name text,\n"
     "  rootpage integer,\n"
     "  sql text\n"
     ")"
  ;
#else
  #define temp_master_schema 0
#endif

  assert( iDb>=0 && iDb<db->nDb );
  assert( db->aDb[iDb].pSchema );

  /* zMasterSchema and zInitScript are set to point at the master schema
  ** and initialisation script appropriate for the database being
  ** initialised. zMasterName is the name of the master table.
  */
  if( !OMIT_TEMPDB && iDb==1 ){
    zMasterSchema = temp_master_schema;
  }else{
    zMasterSchema = master_schema;
  }
  zMasterName = SCHEMA_TABLE(iDb);

  /* Construct the schema tables.  */
  sqlite3SafetyOff(db);
  azArg[0] = zMasterName;
  azArg[1] = "1";
  azArg[2] = zMasterSchema;
  azArg[3] = 0;
  initData.db = db;
  initData.iDb = iDb;
  initData.pzErrMsg = pzErrMsg;
  rc = sqlite3InitCallback(&initData, 3, (char **)azArg, 0);
  if( rc ){
    sqlite3SafetyOn(db);
    return initData.rc;
  }
  pTab = sqlite3FindTable(db, zMasterName, db->aDb[iDb].zName);
  if( pTab ){
    pTab->readOnly = 1;
  }
  sqlite3SafetyOn(db);

  /* Create a cursor to hold the database open
  */
  pDb = &db->aDb[iDb];
  if( pDb->pBt==0 ){
    if( !OMIT_TEMPDB && iDb==1 ){
      DbSetProperty(db, 1, DB_SchemaLoaded);
    }
    return SQLITE_OK;
  }
  rc = sqlite3BtreeCursor(pDb->pBt, MASTER_ROOT, 0, 0, 0, &curMain);
  if( rc!=SQLITE_OK && rc!=SQLITE_EMPTY ){
    sqlite3SetString(pzErrMsg, sqlite3ErrStr(rc), (char*)0);
    return rc;
  }

  /* Get the database meta information.
  **
  ** Meta values are as follows:
  **    meta[0]   Schema cookie.  Changes with each schema change.
  **    meta[1]   File format of schema layer.
  **    meta[2]   Size of the page cache.
  **    meta[3]   Use freelist if 0.  Autovacuum if greater than zero.
  **    meta[4]   Db text encoding. 1:UTF-8 2:UTF-16LE 3:UTF-16BE
  **    meta[5]   The user cookie. Used by the application.
  **    meta[6]   
  **    meta[7]
  **    meta[8]
  **    meta[9]
  **
  ** Note: The #defined SQLITE_UTF* symbols in sqliteInt.h correspond to
  ** the possible values of meta[4].
  */
  if( rc==SQLITE_OK ){
    int i;
    for(i=0; rc==SQLITE_OK && i<sizeof(meta)/sizeof(meta[0]); i++){
      rc = sqlite3BtreeGetMeta(pDb->pBt, i+1, (u32 *)&meta[i]);
    }
    if( rc ){
      sqlite3SetString(pzErrMsg, sqlite3ErrStr(rc), (char*)0);
      sqlite3BtreeCloseCursor(curMain);
      return rc;
    }
  }else{
    memset(meta, 0, sizeof(meta));
  }
  pDb->pSchema->schema_cookie = meta[0];

  /* If opening a non-empty database, check the text encoding. For the
  ** main database, set sqlite3.enc to the encoding of the main database.
  ** For an attached db, it is an error if the encoding is not the same
  ** as sqlite3.enc.
  */
  if( meta[4] ){  /* text encoding */
    if( iDb==0 ){
      /* If opening the main database, set ENC(db). */
      ENC(db) = (u8)meta[4];
      db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 6, 0);
    }else{
      /* If opening an attached database, the encoding much match ENC(db) */
      if( meta[4]!=ENC(db) ){
        sqlite3BtreeCloseCursor(curMain);
        sqlite3SetString(pzErrMsg, "attached databases must use the same"
            " text encoding as main database", (char*)0);
        return SQLITE_ERROR;
      }
    }
  }else{
    DbSetProperty(db, iDb, DB_Empty);
  }
  pDb->pSchema->enc = ENC(db);

  size = meta[2];
  if( size==0 ){ size = MAX_PAGES; }
  pDb->pSchema->cache_size = size;
  sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size);

  /*
  ** file_format==1    Version 3.0.0.
  ** file_format==2    Version 3.1.3.  // ALTER TABLE ADD COLUMN
  ** file_format==3    Version 3.1.4.  // ditto but with non-NULL defaults
  ** file_format==4    Version 3.3.0.  // DESC indices.  Boolean constants
  */
  pDb->pSchema->file_format = meta[1];
  if( pDb->pSchema->file_format==0 ){
    pDb->pSchema->file_format = 1;
  }
  if( pDb->pSchema->file_format>SQLITE_MAX_FILE_FORMAT ){
    sqlite3BtreeCloseCursor(curMain);
    sqlite3SetString(pzErrMsg, "unsupported file format", (char*)0);
    return SQLITE_ERROR;
  }


  /* Read the schema information out of the schema tables
  */
  assert( db->init.busy );
  if( rc==SQLITE_EMPTY ){
    /* For an empty database, there is nothing to read */
    rc = SQLITE_OK;
  }else{
    char *zSql;
    zSql = sqlite3MPrintf(
        "SELECT name, rootpage, sql FROM '%q'.%s",
        db->aDb[iDb].zName, zMasterName);
    sqlite3SafetyOff(db);
    rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0);
    if( rc==SQLITE_ABORT ) rc = initData.rc;
    sqlite3SafetyOn(db);
    sqliteFree(zSql);
#ifndef SQLITE_OMIT_ANALYZE
    if( rc==SQLITE_OK ){
      sqlite3AnalysisLoad(db, iDb);
    }
#endif
    sqlite3BtreeCloseCursor(curMain);
  }
  if( sqlite3MallocFailed() ){
    /* sqlite3SetString(pzErrMsg, "out of memory", (char*)0); */
    rc = SQLITE_NOMEM;
    sqlite3ResetInternalSchema(db, 0);
  }
  if( rc==SQLITE_OK ){
    DbSetProperty(db, iDb, DB_SchemaLoaded);
  }else{
    sqlite3ResetInternalSchema(db, iDb);
  }
  return rc;
}
Beispiel #6
0
/*
** Attempt to read the database schema and initialize internal
** data structures for a single database file.  The index of the
** database file is given by iDb.  iDb==0 is used for the main
** database.  iDb==1 should never be used.  iDb>=2 is used for
** auxiliary databases.  Return one of the SQLITE_ error codes to
** indicate success or failure.
*/
static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
  int rc;
  BtCursor *curMain;
  int size;
  Table *pTab;
  Db *pDb;
  char const *azArg[4];
  int meta[10];
  InitData initData;
  char const *zMasterSchema;
  char const *zMasterName = SCHEMA_TABLE(iDb);

  /*
  ** The master database table has a structure like this
  */
  static const char master_schema[] = 
     "CREATE TABLE sqlite_master(\n"
     "  type text,\n"
     "  name text,\n"
     "  tbl_name text,\n"
     "  rootpage integer,\n"
     "  sql text\n"
     ")"
  ;
#ifndef SQLITE_OMIT_TEMPDB
  static const char temp_master_schema[] = 
     "CREATE TEMP TABLE sqlite_temp_master(\n"
     "  type text,\n"
     "  name text,\n"
     "  tbl_name text,\n"
     "  rootpage integer,\n"
     "  sql text\n"
     ")"
  ;
#else
  #define temp_master_schema 0
#endif

  assert( iDb>=0 && iDb<db->nDb );
  assert( db->aDb[iDb].pSchema );
  assert( sqlite3_mutex_held(db->mutex) );
  assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) );

  /* zMasterSchema and zInitScript are set to point at the master schema
  ** and initialisation script appropriate for the database being
  ** initialised. zMasterName is the name of the master table.
  */
  if( !OMIT_TEMPDB && iDb==1 ){
    zMasterSchema = temp_master_schema;
  }else{
    zMasterSchema = master_schema;
  }
  zMasterName = SCHEMA_TABLE(iDb);

  /* Construct the schema tables.  */
  azArg[0] = zMasterName;
  azArg[1] = "1";
  azArg[2] = zMasterSchema;
  azArg[3] = 0;
  initData.db = db;
  initData.iDb = iDb;
  initData.rc = SQLITE_OK;
  initData.pzErrMsg = pzErrMsg;
  (void)sqlite3SafetyOff(db);
  sqlite3InitCallback(&initData, 3, (char **)azArg, 0);
  (void)sqlite3SafetyOn(db);
  if( initData.rc ){
    rc = initData.rc;
    goto error_out;
  }
  pTab = sqlite3FindTable(db, zMasterName, db->aDb[iDb].zName);
  if( pTab ){
    pTab->tabFlags |= TF_Readonly;
  }

  /* Create a cursor to hold the database open
  */
  pDb = &db->aDb[iDb];
  if( pDb->pBt==0 ){
    if( !OMIT_TEMPDB && iDb==1 ){
      DbSetProperty(db, 1, DB_SchemaLoaded);
    }
    return SQLITE_OK;
  }
  curMain = sqlite3MallocZero(sqlite3BtreeCursorSize());
  if( !curMain ){
    rc = SQLITE_NOMEM;
    goto error_out;
  }
  sqlite3BtreeEnter(pDb->pBt);
  rc = sqlite3BtreeCursor(pDb->pBt, MASTER_ROOT, 0, 0, curMain);
  if( rc!=SQLITE_OK && rc!=SQLITE_EMPTY ){
    sqlite3SetString(pzErrMsg, db, "%s", sqlite3ErrStr(rc));
    goto initone_error_out;
  }

  /* Get the database meta information.
  **
  ** Meta values are as follows:
  **    meta[0]   Schema cookie.  Changes with each schema change.
  **    meta[1]   File format of schema layer.
  **    meta[2]   Size of the page cache.
  **    meta[3]   Use freelist if 0.  Autovacuum if greater than zero.
  **    meta[4]   Db text encoding. 1:UTF-8 2:UTF-16LE 3:UTF-16BE
  **    meta[5]   The user cookie. Used by the application.
  **    meta[6]   Incremental-vacuum flag.
  **    meta[7]
  **    meta[8]
  **    meta[9]
  **
  ** Note: The #defined SQLITE_UTF* symbols in sqliteInt.h correspond to
  ** the possible values of meta[4].
  */
  if( rc==SQLITE_OK ){
    int i;
    for(i=0; i<ArraySize(meta); i++){
      rc = sqlite3BtreeGetMeta(pDb->pBt, i+1, (u32 *)&meta[i]);
      if( rc ){
        sqlite3SetString(pzErrMsg, db, "%s", sqlite3ErrStr(rc));
        goto initone_error_out;
      }
    }
  }else{
    memset(meta, 0, sizeof(meta));
  }
  pDb->pSchema->schema_cookie = meta[0];

  /* If opening a non-empty database, check the text encoding. For the
  ** main database, set sqlite3.enc to the encoding of the main database.
  ** For an attached db, it is an error if the encoding is not the same
  ** as sqlite3.enc.
  */
  if( meta[4] ){  /* text encoding */
    if( iDb==0 ){
      /* If opening the main database, set ENC(db). */
      ENC(db) = (u8)meta[4];
      db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 6, 0);
    }else{
      /* If opening an attached database, the encoding much match ENC(db) */
      if( meta[4]!=ENC(db) ){
        sqlite3SetString(pzErrMsg, db, "attached databases must use the same"
            " text encoding as main database");
        rc = SQLITE_ERROR;
        goto initone_error_out;
      }
    }
  }else{
    DbSetProperty(db, iDb, DB_Empty);
  }
  pDb->pSchema->enc = ENC(db);

  if( pDb->pSchema->cache_size==0 ){
    size = meta[2];
    if( size==0 ){ size = SQLITE_DEFAULT_CACHE_SIZE; }
    if( size<0 ) size = -size;
    pDb->pSchema->cache_size = size;
    sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size);
  }

  /*
  ** file_format==1    Version 3.0.0.
  ** file_format==2    Version 3.1.3.  // ALTER TABLE ADD COLUMN
  ** file_format==3    Version 3.1.4.  // ditto but with non-NULL defaults
  ** file_format==4    Version 3.3.0.  // DESC indices.  Boolean constants
  */
  pDb->pSchema->file_format = (u8)meta[1];
  if( pDb->pSchema->file_format==0 ){
    pDb->pSchema->file_format = 1;
  }
  if( pDb->pSchema->file_format>SQLITE_MAX_FILE_FORMAT ){
    sqlite3SetString(pzErrMsg, db, "unsupported file format");
    rc = SQLITE_ERROR;
    goto initone_error_out;
  }

  /* Ticket #2804:  When we open a database in the newer file format,
  ** clear the legacy_file_format pragma flag so that a VACUUM will
  ** not downgrade the database and thus invalidate any descending
  ** indices that the user might have created.
  */
  if( iDb==0 && meta[1]>=4 ){
    db->flags &= ~SQLITE_LegacyFileFmt;
  }

  /* Read the schema information out of the schema tables
  */
  assert( db->init.busy );
  if( rc==SQLITE_EMPTY ){
    /* For an empty database, there is nothing to read */
    rc = SQLITE_OK;
  }else{
    char *zSql;
    zSql = sqlite3MPrintf(db, 
        "SELECT name, rootpage, sql FROM '%q'.%s",
        db->aDb[iDb].zName, zMasterName);
    (void)sqlite3SafetyOff(db);
#ifndef SQLITE_OMIT_AUTHORIZATION
    {
      int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
      xAuth = db->xAuth;
      db->xAuth = 0;
#endif
      rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0);
#ifndef SQLITE_OMIT_AUTHORIZATION
      db->xAuth = xAuth;
    }
#endif
    if( rc==SQLITE_OK ) rc = initData.rc;
    (void)sqlite3SafetyOn(db);
    sqlite3DbFree(db, zSql);
#ifndef SQLITE_OMIT_ANALYZE
    if( rc==SQLITE_OK ){
      sqlite3AnalysisLoad(db, iDb);
    }
#endif
  }
  if( db->mallocFailed ){
    rc = SQLITE_NOMEM;
    sqlite3ResetInternalSchema(db, 0);
  }
  if( rc==SQLITE_OK || (db->flags&SQLITE_RecoveryMode)){
    /* Black magic: If the SQLITE_RecoveryMode flag is set, then consider
    ** the schema loaded, even if errors occurred. In this situation the 
    ** current sqlite3_prepare() operation will fail, but the following one
    ** will attempt to compile the supplied statement against whatever subset
    ** of the schema was loaded before the error occurred. The primary
    ** purpose of this is to allow access to the sqlite_master table
    ** even when its contents have been corrupted.
    */
    DbSetProperty(db, iDb, DB_SchemaLoaded);
    rc = SQLITE_OK;
  }

  /* Jump here for an error that occurs after successfully allocating
  ** curMain and calling sqlite3BtreeEnter(). For an error that occurs
  ** before that point, jump to error_out.
  */
initone_error_out:
  sqlite3BtreeCloseCursor(curMain);
  sqlite3_free(curMain);
  sqlite3BtreeLeave(pDb->pBt);

error_out:
  if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
    db->mallocFailed = 1;
  }
  return rc;
}
/*
** Attempt to read the database schema and initialize internal
** data structures for a single database file.  The index of the
** database file is given by iDb.  iDb==0 is used for the main
** database.  iDb==1 should never be used.  iDb>=2 is used for
** auxiliary databases.  Return one of the SQLITE_ error codes to
** indicate success or failure.
*/
static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
  int rc;
  BtCursor *curMain;
  int size;
  Table *pTab;
  char const *azArg[5];
  char zDbNum[30];
  int meta[10];
  InitData initData;
  char const *zMasterSchema;
  char const *zMasterName = SCHEMA_TABLE(iDb);

  /*
  ** The master database table has a structure like this
  */
  static const char master_schema[] = 
     "CREATE TABLE sqlite_master(\n"
     "  type text,\n"
     "  name text,\n"
     "  tbl_name text,\n"
     "  rootpage integer,\n"
     "  sql text\n"
     ")"
  ;
#ifndef SQLITE_OMIT_TEMPDB
  static const char temp_master_schema[] = 
     "CREATE TEMP TABLE sqlite_temp_master(\n"
     "  type text,\n"
     "  name text,\n"
     "  tbl_name text,\n"
     "  rootpage integer,\n"
     "  sql text\n"
     ")"
  ;
#else
  #define temp_master_schema 0
#endif

  assert( iDb>=0 && iDb<db->nDb );

  /* zMasterSchema and zInitScript are set to point at the master schema
  ** and initialisation script appropriate for the database being
  ** initialised. zMasterName is the name of the master table.
  */
  if( !OMIT_TEMPDB && iDb==1 ){
    zMasterSchema = temp_master_schema;
  }else{
    zMasterSchema = master_schema;
  }
  zMasterName = SCHEMA_TABLE(iDb);

  /* Construct the schema tables.  */
  sqlite3SafetyOff(db);
  azArg[0] = zMasterName;
  azArg[1] = "1";
  azArg[2] = zMasterSchema;
  sprintf(zDbNum, "%d", iDb);
  azArg[3] = zDbNum;
  azArg[4] = 0;
  initData.db = db;
  initData.pzErrMsg = pzErrMsg;
  rc = sqlite3InitCallback(&initData, 4, (char **)azArg, 0);
  if( rc!=SQLITE_OK ){
    sqlite3SafetyOn(db);
    return rc;
  }
  pTab = sqlite3FindTable(db, zMasterName, db->aDb[iDb].zName);
  if( pTab ){
    pTab->readOnly = 1;
  }
  sqlite3SafetyOn(db);

  /* Create a cursor to hold the database open
  */
  if( db->aDb[iDb].pBt==0 ){
    if( !OMIT_TEMPDB && iDb==1 ) DbSetProperty(db, 1, DB_SchemaLoaded);
    return SQLITE_OK;
  }
  rc = sqlite3BtreeCursor(db->aDb[iDb].pBt, MASTER_ROOT, 0, 0, 0, &curMain);
  if( rc!=SQLITE_OK && rc!=SQLITE_EMPTY ){
    sqlite3SetString(pzErrMsg, sqlite3ErrStr(rc), (char*)0);
    return rc;
  }

  /* Get the database meta information.
  **
  ** Meta values are as follows:
  **    meta[0]   Schema cookie.  Changes with each schema change.
  **    meta[1]   File format of schema layer.
  **    meta[2]   Size of the page cache.
  **    meta[3]   Use freelist if 0.  Autovacuum if greater than zero.
  **    meta[4]   Db text encoding. 1:UTF-8 3:UTF-16 LE 4:UTF-16 BE
  **    meta[5]   The user cookie. Used by the application.
  **    meta[6]   
  **    meta[7]
  **    meta[8]
  **    meta[9]
  **
  ** Note: The hash defined SQLITE_UTF* symbols in sqliteInt.h correspond to
  ** the possible values of meta[4].
  */
  if( rc==SQLITE_OK ){
    int i;
    for(i=0; rc==SQLITE_OK && i<sizeof(meta)/sizeof(meta[0]); i++){
      rc = sqlite3BtreeGetMeta(db->aDb[iDb].pBt, i+1, (u32 *)&meta[i]);
    }
    if( rc ){
      sqlite3SetString(pzErrMsg, sqlite3ErrStr(rc), (char*)0);
      sqlite3BtreeCloseCursor(curMain);
      return rc;
    }
  }else{
    memset(meta, 0, sizeof(meta));
  }
  db->aDb[iDb].schema_cookie = meta[0];

  /* If opening a non-empty database, check the text encoding. For the
  ** main database, set sqlite3.enc to the encoding of the main database.
  ** For an attached db, it is an error if the encoding is not the same
  ** as sqlite3.enc.
  */
  if( meta[4] ){  /* text encoding */
    if( iDb==0 ){
      /* If opening the main database, set db->enc. */
      db->enc = (u8)meta[4];
      db->pDfltColl = sqlite3FindCollSeq(db, db->enc, "BINARY", 6, 0);
    }else{
      /* If opening an attached database, the encoding much match db->enc */
      if( meta[4]!=db->enc ){
        sqlite3BtreeCloseCursor(curMain);
        sqlite3SetString(pzErrMsg, "attached databases must use the same"
            " text encoding as main database", (char*)0);
        return SQLITE_ERROR;
      }
    }
  }

  size = meta[2];
  if( size==0 ){ size = MAX_PAGES; }
  db->aDb[iDb].cache_size = size;

  if( iDb==0 ){
    db->file_format = meta[1];
    if( db->file_format==0 ){
      /* This happens if the database was initially empty */
      db->file_format = 1;
    }

    if( db->file_format==2 || db->file_format==3 ){
      /* File format 2 is treated exactly as file format 1. New 
      ** databases are created with file format 1.
      */ 
      db->file_format = 1;
    }
  }

  /*
  ** file_format==1    Version 3.0.0.
  ** file_format==2    Version 3.1.3.
  ** file_format==3    Version 3.1.4.
  **
  ** Version 3.0 can only use files with file_format==1. Version 3.1.3
  ** can read and write files with file_format==1 or file_format==2.
  ** Version 3.1.4 can read and write file formats 1, 2 and 3.
  */
  if( meta[1]>3 ){
    sqlite3BtreeCloseCursor(curMain);
    sqlite3SetString(pzErrMsg, "unsupported file format", (char*)0);
    return SQLITE_ERROR;
  }

  sqlite3BtreeSetCacheSize(db->aDb[iDb].pBt, db->aDb[iDb].cache_size);

  /* Read the schema information out of the schema tables
  */
  assert( db->init.busy );
  if( rc==SQLITE_EMPTY ){
    /* For an empty database, there is nothing to read */
    rc = SQLITE_OK;
  }else{
    char *zSql;
    zSql = sqlite3MPrintf(
        "SELECT name, rootpage, sql, '%s' FROM '%q'.%s",
        zDbNum, db->aDb[iDb].zName, zMasterName);
    sqlite3SafetyOff(db);
    rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0);
    sqlite3SafetyOn(db);
    sqliteFree(zSql);
    sqlite3BtreeCloseCursor(curMain);
  }
  if( sqlite3_malloc_failed ){
    sqlite3SetString(pzErrMsg, "out of memory", (char*)0);
    rc = SQLITE_NOMEM;
    sqlite3ResetInternalSchema(db, 0);
  }
  if( rc==SQLITE_OK ){
    DbSetProperty(db, iDb, DB_SchemaLoaded);
  }else{
    sqlite3ResetInternalSchema(db, iDb);
  }
  return rc;
}
Beispiel #8
0
void testUpdate() {

	puts("testUpdate()");

	sqlite3 *db;

	char * file = UPDATE_FILE;

	int rc = sqlite3_open(file, &db);

	if (rc != SQLITE_OK) {
		printf("failed open: %d \n", rc);
		return;
	}

	if (db->nDb == 0) {
		puts("backends count is zero");
		goto close;
	}

	Btree *pBt = db->aDb[0].pBt;

	rc = sqlite3BtreeBeginTrans(pBt, 1);
	if (rc != SQLITE_OK) {
		printf("failed begin transaction: %d", rc);
		goto close;
	}

	char* pData = "Test data";
	int nData = strlen(pData);

	BtCursor cur;
	int x = 0;

	for (x = 1; x <= 3; x++) {

		int table = 0;
		rc = sqlite3BtreeCreateTable(pBt, &table, BTREE_INTKEY
						| BTREE_LEAFDATA);
		if (rc != SQLITE_OK) {
			printf("failed create table: %d", rc);
			goto close;
		}

		memset(&cur, 0, sizeof(BtCursor));
		rc = sqlite3BtreeCursor(pBt, table, 0, 0, &cur);
		if (rc != SQLITE_OK) {
			printf("failed get cursor: %d", rc);
			goto close;
		}

		int y = 0;
		for (y = 1; y <= 3; y++) {
			rc = sqlite3BtreeInsert(&cur, NULL, y, pData, nData, 0, 0);
			if (rc != SQLITE_OK) {
				printf("failed insert data: %d", rc);
				goto close;
			}
		}

		rc = sqlite3BtreeCloseCursor(&cur);
		if (rc != SQLITE_OK) {
			printf("failed close cursor: %d", rc);
			goto close;
		}

	}

	rc = sqlite3BtreeCommit(pBt);
	if (rc != SQLITE_OK) {
		printf("failed commit transaction: %d", rc);
	} else {
		puts("success commit transaction");
	}

	sqlite3_close(db);

	rc = sqlite3_open(file, &db);

	if (rc != SQLITE_OK) {
		printf("failed open: %d \n", rc);
		return;
	}

	if (db->nDb == 0) {
		puts("backends count is zero");
		goto close;
	}

	pBt = db->aDb[0].pBt;

	rc = sqlite3BtreeBeginTrans(pBt, 1);
	if (rc != SQLITE_OK) {
		printf("failed begin transaction: %d", rc);
		goto close;
	}

	int pages = 0;

	rc = sqlite3PagerPagecount(pBt->pBt->pPager, &pages);

	if (rc != SQLITE_OK) {
		printf("failed get pages count: %d \n", rc);
		goto close;
	}

	if (pages == 0) {
		puts("pages count is zero");
		goto close;
	}

	printf("pages count: %d \n", pages);


	pData = "Data test";
	nData = strlen(pData);

	x = 0;

	for (x = 1; x <= pages; x++) {

		memset(&cur, 0, sizeof(BtCursor));
		rc = sqlite3BtreeCursor(pBt, x, 1, 0, &cur);
		if (rc != SQLITE_OK) {
			printf("failed get cursor: %d", rc);
			goto close;
		}

		int next = 0;
		rc = sqlite3BtreeFirst(&cur, &next);
		if (rc != SQLITE_OK) {
			printf("failed first(): %d \n", rc);
			goto closeCursor;
		}

		if (next != 0) {
			puts("cursor is empty");
			goto closeCursor;
		}

		sqlite3BtreeCacheOverflow(&cur);

		do {

			rc = sqlite3BtreePutData(&cur,0,nData,pData);
			if (rc != SQLITE_OK) {
				printf("failed putData(): %d \n", rc);
				goto closeCursor;
			}

			puts("data updated");

		} while (SQLITE_OK == sqlite3BtreeNext(&cur, &next) && next == 0);

		closeCursor:
		rc = sqlite3BtreeCloseCursor(&cur);
		if (rc != SQLITE_OK) {
			printf("failed close cursor: %d", rc);
			goto close;
		}

	}

	rc = sqlite3BtreeCommit(pBt);
	if (rc != SQLITE_OK) {
		printf("failed commit transaction: %d", rc);
	} else {
		puts("success commit transaction");
	}


	close:
	sqlite3_close(db);

}
Beispiel #9
0
/*
** Reset an Agg structure.  Delete all its contents.
**
** For installable aggregate functions, if the step function has been
** called, make sure the finalizer function has also been called.  The
** finalizer might need to free memory that was allocated as part of its
** private context.  If the finalizer has not been called yet, call it
** now.
**
** If db is NULL, then this is being called from sqliteVdbeReset(). In
** this case clean up all references to the temp-table used for
** aggregates (if it was ever opened).
**
** If db is not NULL, then this is being called from with an OP_AggReset
** opcode. Open the temp-table, if it has not already been opened and
** delete the contents of the table used for aggregate information, ready
** for the next round of aggregate processing.
*/
int sqlite3VdbeAggReset(sqlite3 *db, Agg *pAgg, KeyInfo *pKeyInfo){
  int rc = 0;
  BtCursor *pCsr = pAgg->pCsr;

  assert( (pCsr && pAgg->nTab>0) || (!pCsr && pAgg->nTab==0)
         || sqlite3_malloc_failed );

  /* If pCsr is not NULL, then the table used for aggregate information
  ** is open. Loop through it and free the AggElem* structure pointed at
  ** by each entry. If the finalizer has not been called for an AggElem,
  ** do that too. Finally, clear the btree table itself.
  */
  if( pCsr ){
    int res;
    assert( pAgg->pBtree );
    assert( pAgg->nTab>0 );

    rc=sqlite3BtreeFirst(pCsr, &res);
    while( res==0 && rc==SQLITE_OK ){
      AggElem *pElem;
      rc = sqlite3BtreeData(pCsr, 0, sizeof(AggElem*), (char *)&pElem);
      if( res!=SQLITE_OK ){
        return rc;
      }
      assert( pAgg->apFunc!=0 );
      freeAggElem(pElem, pAgg);
      rc=sqlite3BtreeNext(pCsr, &res);
    }
    if( rc!=SQLITE_OK ){
      return rc;
    }

    sqlite3BtreeCloseCursor(pCsr);
    sqlite3BtreeClearTable(pAgg->pBtree, pAgg->nTab);
  }else{ 
    /* The cursor may not be open because the aggregator was never used,
    ** or it could be that it was used but there was no GROUP BY clause.
    */
    if( pAgg->pCurrent ){
      freeAggElem(pAgg->pCurrent, pAgg);
    }
  }

  /* If db is not NULL and we have not yet and we have not yet opened
  ** the temporary btree then do so and create the table to store aggregate
  ** information.
  **
  ** If db is NULL, then close the temporary btree if it is open.
  */
  if( db ){
    if( !pAgg->pBtree ){
      assert( pAgg->nTab==0 );
      rc = sqlite3BtreeFactory(db, ":memory:", 0, TEMP_PAGES, &pAgg->pBtree);
      if( rc!=SQLITE_OK ) return rc;
      sqlite3BtreeBeginTrans(pAgg->pBtree, 1);
      rc = sqlite3BtreeCreateTable(pAgg->pBtree, &pAgg->nTab, 0);
      if( rc!=SQLITE_OK ) return rc;
    }
    assert( pAgg->nTab!=0 );

    rc = sqlite3BtreeCursor(pAgg->pBtree, pAgg->nTab, 1,
        sqlite3VdbeRecordCompare, pKeyInfo, &pAgg->pCsr);
    if( rc!=SQLITE_OK ) return rc;
  }else{
    if( pAgg->pBtree ){
      sqlite3BtreeClose(pAgg->pBtree);
      pAgg->pBtree = 0;
      pAgg->nTab = 0;
    }
    pAgg->pCsr = 0;
  }

  if( pAgg->apFunc ){ 
    sqliteFree(pAgg->apFunc);
    pAgg->apFunc = 0;
  }
  pAgg->pCurrent = 0;
  pAgg->nMem = 0;
  pAgg->searching = 0;
  return SQLITE_OK;
}
Beispiel #10
0
/*
 * Use Bulk Get/Put to copy the given number of pages worth of
 * records from the source database to the destination database,
 * this function should be called until all tables are copied, at
 * which point it will return SQLITE_DONE.  Both Btrees need to
 * have transactions before calling this function.
 * p->pSrc - Source Btree
 * p->tables - Contains a list of iTables to copy, gotten using
 *          btreeGetTables().
 * p->currentTable - Index in tables of the current table being copied.
 * p->srcCur -  Cursor on the current source table being copied.
 * p->pDest - Destiniation Btree.
 * p->destCur - BtCursor on the destination table being copied into.
 * pages - Number of pages worth of data to copy.
 */
static int btreeCopyPages(sqlite3_backup *p, int *pages)
{
	DB *dbp;
	DBT dataOut, dataIn;
	char bufOut[MULTI_BUFSIZE], bufIn[MULTI_BUFSIZE];
	int ret, rc, copied, srcIsDupIndex;
	void *in, *out, *app;

	ret = 0;
	rc = SQLITE_OK;
	dbp = NULL;
	copied = 0;
	memset(&dataOut, 0, sizeof(dataOut));
	memset(&dataIn, 0, sizeof(dataIn));
	dataOut.flags = DB_DBT_USERMEM;
	dataIn.flags = DB_DBT_USERMEM;
	dataOut.data = bufOut;
	dataOut.ulen = sizeof(bufOut);
	dataIn.data = bufIn;
	dataIn.ulen = sizeof(bufIn);

	while (*pages < 0 || *pages > copied) {
		/* No tables left to copy */
		if (p->tables[p->currentTable] == -1) {
			u32 val;
			/*
			 * Update the schema file format and largest rootpage
			 * in the meta data.  Other meta data values should
			 * not be changed.
			 */
			sqlite3BtreeGetMeta(p->pSrc, 1, &val);
			if (p->pSrc->db->errCode == SQLITE_BUSY) {
				rc = SQLITE_BUSY;
				goto err;
			}
			rc = sqlite3BtreeUpdateMeta(p->pDest, 1, val);
			if (rc != SQLITE_OK)
				goto err;
			sqlite3BtreeGetMeta(p->pSrc, 3, &val);
		       if (p->pSrc->db->errCode == SQLITE_BUSY) {
				rc = SQLITE_BUSY;
				goto err;
			}
			rc = sqlite3BtreeUpdateMeta(p->pDest, 3, val);
			if (rc != SQLITE_OK)
				goto err;
			ret = SQLITE_DONE;
			goto err;
		}
		/* If not currently copying a table, get the next table. */
		if (!p->srcCur) {
			rc = btreeGetUserTable(p->pSrc, p->srcTxn, &dbp,
			    p->tables[p->currentTable]);
			if (rc != SQLITE_OK)
				goto err;
			assert(dbp);
			memset(&p->destCur, 0, sizeof(p->destCur));
			/*
			 * Open a cursor on the destination table, this will
			 * create the table and allow the Btree to manage the
			 * DB object.
			 */
			sqlite3BtreeCursor(p->pDest, p->tables[p->currentTable],
			    1, dbp->app_private, &p->destCur);
			if ((rc = p->destCur.error) != SQLITE_OK) {
				app = dbp->app_private;
				dbp->close(dbp, DB_NOSYNC);
				if (app)
					sqlite3DbFree(p->pSrcDb, app);
				goto err;
			}
			/* Open a cursor on the source table. */
			if ((ret = dbp->cursor(dbp,
			    p->srcTxn, &p->srcCur, 0)) != 0)
				goto err;
			dbp = 0;
		}
		srcIsDupIndex = isDupIndex((p->tables[p->currentTable] & 1) ?
		    BTREE_INTKEY : 0, p->pSrc->pBt->dbStorage,
		    p->srcCur->dbp->app_private, p->srcCur->dbp);
		/*
		 * Copy the current table until the given number of
		 * pages is copied, or the entire table has been copied.
		 */
		while (*pages < 0 || *pages > copied) {
			DBT key, data;
			memset(&key, 0, sizeof(key));
			memset(&data, 0, sizeof(data));
			/* Do a Bulk Get from the source table. */
			ret = p->srcCur->get(p->srcCur, &key, &dataOut,
			    DB_NEXT | DB_MULTIPLE_KEY);
			if (ret == DB_NOTFOUND)
				break;
			if (ret != 0)
				goto err;
			/* Copy the records into the Bulk buffer. */
			DB_MULTIPLE_INIT(out, &dataOut);
			DB_MULTIPLE_WRITE_INIT(in, &dataIn);
			DB_MULTIPLE_KEY_NEXT(out, &dataOut, key.data,
			    key.size, data.data, data.size);
			while (out) {
				/*
				 * Have to translate the index formats if they
				 * are not the same.
				 */
				if (p->destCur.isDupIndex != srcIsDupIndex) {
					if (srcIsDupIndex) {
						p->destCur.key = key;
						p->destCur.data = data;
						if (!btreeCreateIndexKey(
						    &p->destCur)) {
							rc = SQLITE_NOMEM;
							goto err;
						}
						DB_MULTIPLE_KEY_WRITE_NEXT(in,
						    &dataIn,
						    p->destCur.index.data,
						    p->destCur.index.size,
						    p->destCur.data.data, 0);
					} else {
						/* Copy the key into the cursor
						 * index since spliting the key
						 * requires changing the
						 * internal memory.
						 */
						if (!allocateCursorIndex(
						    &p->destCur, key.size)) {
							rc = SQLITE_NOMEM;
							goto err;
						}
						memcpy(p->destCur.index.data,
						    key.data, key.size);
						p->destCur.index.size =
						    key.size;
						p->destCur.key.data =
						    p->destCur.index.data;
						p->destCur.key.size =
						    p->destCur.index.size;
						splitIndexKey(&p->destCur);
						DB_MULTIPLE_KEY_WRITE_NEXT(
						    in, &dataIn,
						    p->destCur.key.data,
						    p->destCur.key.size,
						    p->destCur.data.data,
						    p->destCur.data.size);
					}
				} else
					DB_MULTIPLE_KEY_WRITE_NEXT(in, &dataIn,
					    key.data, key.size,
					    data.data, data.size);
				DB_MULTIPLE_KEY_NEXT(out, &dataOut,
				    key.data, key.size,
				    data.data, data.size);
			}
			/* Insert into the destination table. */
			dbp = p->destCur.cached_db->dbp;
			if ((ret = dbp->put(dbp, p->pDest->savepoint_txn,
			    &dataIn, 0, DB_MULTIPLE_KEY)) != 0)
				goto err;
			dbp = NULL;
			copied += MULTI_BUFSIZE/SQLITE_DEFAULT_PAGE_SIZE;
		}
		/*
		 * Done copying the current table, time to look for a new
		 * table to copy.
		 */
		if (ret == DB_NOTFOUND) {
			ret = 0;
			rc = sqlite3BtreeCloseCursor(&p->destCur);
			if (p->srcCur) {
				app = p->srcCur->dbp->app_private;
				dbp = p->srcCur->dbp;
				p->srcCur->close(p->srcCur);
				ret = dbp->close(dbp, DB_NOSYNC);
				if (app)
					sqlite3DbFree(p->pSrcDb, app);
			}
			p->srcCur = NULL;
			if (ret != 0 || rc != SQLITE_OK)
				goto err;
			p->currentTable += 1;
		}
	}
	goto done;
err:	if (ret == SQLITE_DONE)
		return ret;
done:	return MAP_ERR(rc, ret);
}