void test(int newdb)
{
    const char * sSQL;
    char * pErrMsg = 0;
    int ret = 0;
    sqlite3 * db = 0;

    if(newdb) {
        ::DeleteFileA("encrypt.db");
    }

    //创建数据库
    ret = sqlite3_open("encrypt.db", &db);
    //添加密码
    if(newdb) {
        ret = sqlite3_key( db, "dcg", 3 );
    } else {
        ret = sqlite3_key(db, "abc", 3);
    }

    //在内存数据库中创建表
    sSQL = "create table files(path TEXT PRIMARY KEY, content BLOB, time INTEGER);";
    sqlite3_exec( db, sSQL, _callback_exec, 0, &pErrMsg );
    if(newdb) {
        //插入数据
        sSQL = "insert into files values(?,?,?);";
        sqlite3_stmt* stmt;
        int src;
        src = sqlite3_prepare_v2(db, sSQL, strlen(sSQL), &stmt, NULL);
        src = sqlite3_bind_text(stmt,1, "/global.dat", -1, SQLITE_STATIC);
        src = sqlite3_bind_blob(stmt,2, "zhaoyun", 7, SQLITE_STATIC);
        src = sqlite3_bind_int(stmt, 3, 100);
        src = sqlite3_step(stmt);
        src = sqlite3_total_changes(db);
        sqlite3_finalize(stmt);
        // sqlite3_exec( db, sSQL, _callback_exec, 0, &pErrMsg );
    }

    if(newdb) {
        ret = sqlite3_rekey( db, "abc", 3);
    }

    //取得数据并显示
    sSQL = "select * from files;";
    sqlite3_exec( db, sSQL, _callback_exec, 0, &pErrMsg );

    //关闭数据库
    sqlite3_close(db);

    db = 0;
}
Beispiel #2
0
database::database(const std::string &path, const void *pKey, int nKey)
    : m_path(path)
{
    // create database
    sqlite3* handle = NULL;

    int err = sqlite3_open_v2(path.c_str(), &handle,
                              SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
                              NULL);

    if (err != SQLITE_OK) {
        // error!
    }
    else {
        if (pKey && (nKey > 0)) {
            err = sqlite3_key(handle, pKey, nKey);
            std::cout << "sqlite key error " << err << "\n";
            if (err != SQLITE_OK) {
                sqlite3_close(handle);
                return ;
            }
        }

        m_dbHandle = handle;
    }
}
Beispiel #3
0
void HHVM_METHOD(SQLite3, open,
                 const String& filename,
                 int64_t flags /* = SQLITE3_OPEN_READWRITE |
                   SQLITE3_OPEN_CREATE */,
                 const Variant& encryption_key /* = null */) {
  auto *data = Native::data<SQLite3>(this_);
  if (data->m_raw_db) {
    throw Exception("Already initialized DB Object");
  }

  String fname;
  if (strncmp(filename.data(), ":memory:", 8) != 0) {
    fname = File::TranslatePath(filename);
  } else {
    fname = filename; // in-memory db
  }

  if (sqlite3_open_v2(fname.data(), &data->m_raw_db, flags, nullptr)
      != SQLITE_OK) {
    throw Exception("Unable to open database: %s",
                    sqlite3_errmsg(data->m_raw_db));
  }

#ifdef SQLITE_HAS_CODEC
  const String& str_encryption_key = encryption_key.isNull()
                                   ? null_string
                                   : encryption_key.toString();
  if (!str_encryption_key.empty() &&
      sqlite3_key(data->m_raw_db, str_encryption_key.data(),
      str_encryption_key.size()) != SQLITE_OK) {
    throw Exception("Unable to open database: %s",
                    sqlite3_errmsg(data->m_raw_db));
  }
#endif
}
Beispiel #4
0
void c_SQLite3::t_open(CStrRef filename,
                       int64 flags /* = k_SQLITE3_OPEN_READWRITE |
                                      k_SQLITE3_OPEN_CREATE */,
                       CStrRef encryption_key /* = null_string */) {
  INSTANCE_METHOD_INJECTION_BUILTIN(SQLite3, SQLite3::open);
  if (m_raw_db) {
    throw Exception("Already initialized DB Object");
  }

  String fname;
  if (strncmp(filename.data(), ":memory:", 8) != 0) {
    fname = File::TranslatePath(filename);
  } else {
    fname = filename; // in-memory db
  }

  if (sqlite3_open_v2(fname.data(), &m_raw_db, flags, NULL) != SQLITE_OK) {
    throw Exception("Unable to open database: %s", sqlite3_errmsg(m_raw_db));
  }

#ifdef SQLITE_HAS_CODEC
  if (!encryption_key.empty() &&
      sqlite3_key(m_raw_db, encryption_key.data(), encryption_key.size())
      != SQLITE_OK) {
    throw Exception("Unable to open database: %s", sqlite3_errmsg(m_raw_db));
  }
#endif
}
Beispiel #5
0
void $CMD_NAME$::open()
{
#ifdef WIN32
    string despath = CCFileUtils::sharedFileUtils()->fullPathForFilename(dbsrcFileName.c_str()) ;
#else
    string despath = CCFileUtils::sharedFileUtils()->getWritablePath()+dbdesFileName;

    if (!Utils::isFileExist(despath))
    {
        string srcpath = CCFileUtils::sharedFileUtils()->fullPathForFilename(dbsrcFileName.c_str()) ;
        Utils::FileCopy( srcpath, despath);
    }
#endif

    result = sqlite3_open( despath.c_str() , &pDB);
    CCAssert( result == SQLITE_OK , "打开数据库失败($CMD_NAME$)");

    sqlite3_key(pDB, "1234", 4);

    resultArray = CCArray::create();
    resultArray->retain();

    resultDictionary = CCDictionary::create();
    resultDictionary->retain();
}
Beispiel #6
0
// DBをオープン
sqlite3* DataManager::openDB()
{
	// DBファイルを開いた時間を記憶しておく(処理時間計測のため)
	_dbOpenTime = std::chrono::system_clock::now();
	
	// SQLiteから読込
	std::string dbPath = FileUtils::getInstance()->getWritablePath() + DB_FILE_NAME_ENC;
	
	sqlite3 *db = nullptr;
	// DBファイルオープン
	auto status = sqlite3_open(dbPath.c_str(), &db);
	if(status != SQLITE_OK)
	{
		CCLOG("▼sqlite3_open failed.");
		return nullptr;
	}
	// 暗号化する
	status = sqlite3_key(db, ENCRYPT_DB_PASSWORD, (int)strlen(ENCRYPT_DB_PASSWORD));
	if(status != SQLITE_OK)
	{
		CCLOG("▼sqlite3_key failed.");
		return nullptr;
	}
	
	CCLOG("○DB opened successfully. File : %s",dbPath.c_str());
	
	return db;
}
Beispiel #7
0
void np_config_remove_section(NetPhoneConfig *npconfig, LpSection *section){
#ifdef HAVE_SQLITE3
	char szSQL[128];
	sprintf(szSQL,"DELETE FROM ua_config WHERE  section = '%s';",section->name);

	if(!npconfig->db)
	{
		if (sqlite3_open(npconfig->filename,&npconfig->db) == SQLITE_OK)
		{
			sqlite3_key(npconfig->db,SQLITE3_KEY,SQLITE3_KEY_LEN);
			sqlite3_exec(npconfig->db,szSQL,0,0, 0);
			np_message("np_config_remove_section: sqlite3_exec %s\n", szSQL);
			sqlite3_close(npconfig->db);
		}
	  npconfig->db = NULL;	
	}else
	{
		sqlite3_exec(npconfig->db,szSQL,0,0, 0);
		np_message("np_config_remove_section: sqlite3_exec %s\n", szSQL);
	}
	
#endif
	npconfig->sections=np_list_remove(npconfig->sections,(void *)section);
	np_section_destroy(section);
}
Beispiel #8
0
int sqlite3_key_v2(sqlite3 *db, const char *zDbName, const void *zKey, int nKey)
{
    BOTANSQLITE_TRACE("sqlite3_key_v2");
    //We don't use zDbName. Pass-through to the old sqlite_key
    (void)(zDbName);
    return sqlite3_key(db, zKey, nKey);
}
Beispiel #9
0
void lp_config_remove_section(LpConfig *lpconfig, LpSection *section){
#ifdef HAVE_SQLITE3
	char szSQL[128];
	sprintf(szSQL,"DELETE FROM ua_config WHERE  section = '%s';",section->name);

	if(!lpconfig->db)
	{
		if (sqlite3_open(lpconfig->filename,&lpconfig->db) == SQLITE_OK)
		{
			sqlite3_key(lpconfig->db,SQLITE3_KEY,SQLITE3_KEY_LEN);

			sqlite3_exec(lpconfig->db,szSQL,0,0, 0);
			ms_message("lp_config_remove_section: sqlite3_exec %s", szSQL);
			sqlite3_close(lpconfig->db);
		}
		lpconfig->db = NULL;	
	}else
	{
		sqlite3_exec(lpconfig->db,szSQL,0,0, 0);
		ms_message("lp_config_remove_section: sqlite3_exec %s", szSQL);
	}

#endif
	lpconfig->sections=ms_list_remove(lpconfig->sections,(void *)section);
	lp_section_destroy(section);
}
Beispiel #10
0
void DB_Bianse::open() 
{ 
	#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) 
	// sqlite不能读取ANDROID apk里的db文件 
	string despath = CCFileUtils::sharedFileUtils()->getWritablePath() + dbdesFileName; 
	string despathMD5 = CCFileUtils::sharedFileUtils()->getWritablePath() + CCFileUtils::sharedFileUtils()->MD5Filename(dbdesFileName.c_str()); 
	string newValue = CCUserDefault::sharedUserDefault()->getStringForKey(KEY_OF_CODEVERSION);
	newValue += "_" + Utils::itos(CCUserDefault::sharedUserDefault()->getIntegerForKey(KEY_OF_RESOURCEVERSION));
	string key = dbdesFileName;
	string value = CCUserDefault::sharedUserDefault()->getStringForKey(key.c_str());
	if (!CCFileUtils::sharedFileUtils()->isFileExist(despath) || 
		value.empty() || 
		value.compare(newValue) != 0)
	{ 
		Utils::FileCopy(dbsrcFileName, despathMD5); 
		CCUserDefault::sharedUserDefault()->setStringForKey(key.c_str(), newValue);
	}
	despath = despathMD5; 
	#else 
	string despath = CCFileUtils::sharedFileUtils()->MD5fullPathForFilename(dbsrcFileName.c_str()); 
	#endif 
	 
	result = sqlite3_open( despath.c_str() , &pDB); 
	CCAssert( result == SQLITE_OK , "打开数据库失败(DB_Bianse)"); 
	 
	sqlite3_key(pDB, "woshixiaopingguo", 4); 
	 
	resultArray = CCArray::create(); 
	resultArray->retain(); 
	 
	resultDictionary = CCDictionary::create(); 
	resultDictionary->retain(); 
} 
Beispiel #11
0
int CppSQLite3DB::setKey(const char* szPass, int length)
{
	int nRet = sqlite3_key(mpDB, szPass, length );
	if (nRet != SQLITE_OK)
	{
		const char* szError = sqlite3_errmsg(mpDB);
		throw CppSQLite3Exception(nRet, (char*)szError, DONT_DELETE_MSG);
	}
	return nRet;
}
Beispiel #12
0
void testSQL()
{
    sqlite3* db=NULL;
    int success = sqlite3_open("my.db", &db);

    if(success != SQLITE_OK)
    {
        log("DB failed2");
        return;
    }

    if(!db)
    {
        log("DB failed");
        return;
    }
    std::string key="abadgsfdg";
    sqlite3_key(db, key.c_str(), key.size());

    success = sqlite3_exec(db, "SELECT count(*) FROM sqlite_master;", NULL, NULL, NULL);
    if(success == SQLITE_OK)
    {
        log("DB success");
        success = sqlite3_exec(db, "CREATE TABLE IF NOT EXISTS mytbl(mid INTEGER PRIMARY KEY AUTOINCREMENT, val TEXT)", NULL, NULL, NULL);
        if(success == SQLITE_OK)
        {
            log("DB query");
            sqlite3_exec(db, "BEGIN IMMEDIATE TRANSACTION", NULL, NULL, NULL);
            for(int i=0; i<100; ++i)
            {

                success = sqlite3_exec(db, "INSERT INTO mytbl(val) VALUES ('aaa')", NULL, NULL, NULL);
                if(success != SQLITE_OK)
                {
                    log("insert err %d", i);
                }
//                else
//                {
//                    std::cout << i << std::endl;
//                    std::cout.flush();
//                }
            }
            sqlite3_exec(db, "COMMIT TRANSACTION", NULL, NULL, NULL);
        }
    }
    else
    {
        log("DB failed");
    }

    sqlite3_close(db);
}
Beispiel #13
0
// Set the key for the current sqlite database instance.
void Database::key(const std::string& aKey) const
{
    int pass_len = static_cast<int>(aKey.length());
#ifdef SQLITE_HAS_CODEC
    if (pass_len > 0) {
        const int ret = sqlite3_key(mpSQLite, aKey.c_str(), pass_len);
        check(ret);
    }
#else // SQLITE_HAS_CODEC
    if (pass_len > 0) {
        const SQLite::Exception exception("No encryption support, recompile with SQLITE_HAS_CODEC to enable.");
        throw exception;
    }
#endif // SQLITE_HAS_CODEC
}
void native_key_str(JNIEnv* env, jobject object, jstring jKey)
{
  sqlite3 * handle = (sqlite3 *)env->GetIntField(object, offset_db_handle);

  char const * key = env->GetStringUTFChars(jKey, NULL);
  jsize keyLen = env->GetStringUTFLength(jKey);

  if ( keyLen > 0 ) {
    int status = sqlite3_key(handle, key, keyLen);
    if ( status != SQLITE_OK ) {
        throw_sqlite3_exception(env, handle);
    }
  }
  env->ReleaseStringUTFChars(jKey, key);
}
Beispiel #15
0
bool CppSQLite3DB::setkey(const char *key)
{
#ifdef SQLITE_HAS_CODEC
    if (!key) {
        return false;
    }
    
    int rc = sqlite3_key(mpDB, key, (int)strlen(key));
    if (rc != SQLITE_OK) {
		throw CppSQLite3Exception(rc, "setkey error");
    }
	
    return (rc == SQLITE_OK);
#else
    return false;
#endif
}
void native_key_char(JNIEnv* env, jobject object, jcharArray jKey)
{
  char *keyUtf8        = 0;
  int lenUtf8          = 0;
  jchar* keyUtf16      = 0;
  jsize lenUtf16       = 0;
  UErrorCode status    = U_ZERO_ERROR;
  UConverter *encoding = 0;

  sqlite3 * handle = (sqlite3 *)env->GetIntField(object, offset_db_handle);

  keyUtf16 = env->GetCharArrayElements(jKey, 0);
  lenUtf16 = env->GetArrayLength(jKey);

  // no key, bailing out.
  if ( lenUtf16 == 0 ) goto done;

  encoding = ucnv_open("UTF-8", &status);
  if( U_FAILURE(status) ) {
    throw_sqlite3_exception(env, "native_key_char: opening encoding converter failed");
    goto done;
  }

  lenUtf8 = ucnv_fromUChars(encoding, NULL, 0, keyUtf16, lenUtf16, &status);
  status = (status == U_BUFFER_OVERFLOW_ERROR) ? U_ZERO_ERROR : status;
  if( U_FAILURE(status) ) {
    throw_sqlite3_exception(env, "native_key_char: utf8 length unknown");
    goto done;
  }

  keyUtf8 = (char*) malloc(lenUtf8 * sizeof(char));
  ucnv_fromUChars(encoding, keyUtf8, lenUtf8, keyUtf16, lenUtf16, &status);
  if( U_FAILURE(status) ) {
    throw_sqlite3_exception(env, "native_key_char: utf8 conversion failed");
    goto done;
  }

  if ( sqlite3_key(handle, keyUtf8, lenUtf8) != SQLITE_OK ) {
    throw_sqlite3_exception(env, handle);
  }

done:
  env->ReleaseCharArrayElements(jKey, keyUtf16, 0);
  if(encoding != 0) ucnv_close(encoding);
  if(keyUtf8 != 0)  free(keyUtf8);
}
Beispiel #17
0
int lp_config_sync(LpConfig *lpconfig){
#ifdef HAVE_SQLITE3
	lpconfig->db = NULL;
	if (lpconfig->filename==NULL) return -1;

	if (sqlite3_open(lpconfig->filename,&lpconfig->db) == SQLITE_OK)
	{
		sqlite3_key(lpconfig->db,SQLITE3_KEY,SQLITE3_KEY_LEN);

		if (!sqlite3_table_new(lpconfig->db))
		{
			//sqlite3_table_empty(lpconfig->db);
			//ms_warning("Database update: %s\n", sqlite3_errmsg(lpconfig->db));
		}

		ms_list_for_each2(lpconfig->sections,(void (*)(void *,void*))lp_section_write,(void *)lpconfig->db);
		sqlite3_close(lpconfig->db);
	}else{
		ms_warning("Can't open database: %s\n", sqlite3_errmsg(lpconfig->db));
	}
	lpconfig->db = NULL;
#else
	FILE *file;
	if (lpconfig->filename==NULL) return -1;
#ifndef WIN32
	/* don't create group/world-accessible files */
	(void) umask(S_IRWXG | S_IRWXO);
#endif

#ifdef _MSC_VER
	file=fopen(lpconfig->filename,"w+b");
#else
	file=fopen(lpconfig->filename,"w");
#endif // _MSC_VER

	if (file==NULL){
		ms_warning("Could not write %s !",lpconfig->filename);
		return -1;
	}
	ms_list_for_each2(lpconfig->sections,(void (*)(void *,void*))lp_section_write,(void *)file);
	fclose(file);
#endif // HAVE_SQLITE3
	lpconfig->modified=0;
	return 0;
}
Beispiel #18
0
int np_config_sync(NetPhoneConfig *npconfig){
#ifdef HAVE_SQLITE3
	npconfig->db = NULL;
	if (npconfig->filename==NULL) return -1;
	
	if (sqlite3_open(npconfig->filename,&npconfig->db) == SQLITE_OK)
	{
		sqlite3_key(npconfig->db,SQLITE3_KEY,SQLITE3_KEY_LEN);

		if (!sqlite3_table_new(npconfig->db))
		{
			
		}

		np_list_for_each2(npconfig->sections,(void (*)(void *,void*))np_section_write,(void *)npconfig->db);
		sqlite3_close(npconfig->db);
	}else{
		np_warning("Can't open database: %s\n", sqlite3_errmsg(npconfig->db));
	}
	npconfig->db = NULL;
#else
	FILE *file;
	if (npconfig->filename==NULL) return -1;
#ifndef WIN32
	/* don't create group/world-accessible files */
	(void) umask(S_IRWXG | S_IRWXO);
#endif

#ifdef _MSC_VER
	file=fopen(npconfig->filename,"w+b");
#else
	file=fopen(npconfig->filename,"w");
#endif // _MSC_VER

	if (file==NULL){
		np_warning("Could not write %s !\n",npconfig->filename);
		return -1;
	}
	np_list_for_each2(npconfig->sections,(void (*)(void *,void*))np_section_write,(void *)file);
	fclose(file);
#endif // HAVE_SQLITE3
	npconfig->modified=0;
	return 0;
}
Beispiel #19
0
int IniFileTransToSqlFileMain()
{
	char szValue[MAX_PATH];
	char szCfgFile[MAX_PATH];

	SKNL3GetCurrentAppPath(szCfgFile, sizeof(szCfgFile));
	sprintf(szCfgFile, "%s%s", szCfgFile, "inisql.ini");

	DWORD dwRet = 0;
	::GetPrivateProfileString("OUTPUT", "SQLFILE", "", szValue, sizeof(szValue), szCfgFile);
	if(strlen(szValue) == 0)
	{
		printf("无法获取SQL输出文件信息In file[%s]\n", szCfgFile);
		return -1;
	}

	if(PathFileExists(szValue))
	{
		DeleteFile(szValue);
	}
	sqlite3* sql;
	if(SQLITE_OK != sqlite3_open(szValue, &sql))
	{
		printf("无法创建%s\n", szValue);
		return -2;
	}

	::GetPrivateProfileString("OUTPUT", "SQLPASSWORD", "", szValue, sizeof(szValue), szCfgFile);
	if(strlen(szValue) != 0)
	{
		printf("设置SQL密码为%s\n", szValue);
		if(SQLITE_OK != sqlite3_key(sql, szValue, strlen(szValue)))
		{
			printf("设置SQL密码失败\n");
			sqlite3_close(sql);
			return -3;
		}
	}

	IniFileTransToSqlFile(szCfgFile, sql);
	sqlite3_close(sql);
	return 0;
}
 void native_key(JNIEnv* env, jobject object, jbyteArray jKey) {
   int rc = 0;
   int index = 0;
   jsize size = 0;
   jbyte *key = 0;
   sqlite3 *handle = NULL;
   handle = (sqlite3 *)env->GetLongField(object, offset_db_handle);
   if(handle == NULL){
     LOGE("env->GetLongField returned NULL when retrieving sqlite3 *\n");
   }
   key = env->GetByteArrayElements(jKey, NULL);
   size = env->GetArrayLength(jKey);
   if(key == NULL || size == 0) goto done;
   rc = sqlite3_key(handle, key, size);
   if(rc != SQLITE_OK) {
     throw_sqlite3_exception(env, handle);
   }
 done:
   if(key) env->ReleaseByteArrayElements(jKey, key, JNI_ABORT);
 }
 void native_key_mutf8(JNIEnv* env, jobject object, jcharArray jKey) {
   int rc;
   int idx;
   jint releaseElements = 0;
   jboolean arrayIsCopy;
   sqlite3 *handle = (sqlite3 *)env->GetLongField(object, offset_db_handle);
   jsize sz = env->GetArrayLength(jKey);
   jchar* jKeyChar = env->GetCharArrayElements(jKey, &arrayIsCopy);
   jstring key = env->NewString(jKeyChar, sz);
   const char* password = env->GetStringUTFChars(key, JNI_FALSE);
   int password_sz = env->GetStringUTFLength(key);
   if(password_sz > 0){
     rc = sqlite3_key(handle, password, password_sz);
     if(rc != SQLITE_OK){
       throw_sqlite3_exception(env, handle);
     }
   }
   env->ReleaseCharArrayElements(jKey, jKeyChar, JNI_ABORT);
   env->ReleaseStringUTFChars(key, password);
 }
Beispiel #22
0
bool Handle::setCipherKey(const void *data, int size)
{
#ifdef SQLITE_HAS_CODEC
    int rc = sqlite3_key((sqlite3 *) m_handle, data, size);
    if (rc == SQLITE_OK) {
        m_error.reset();
        return true;
    }
    Error::ReportSQLite(m_tag, path, Error::HandleOperation::SetCipherKey, rc,
                        sqlite3_extended_errcode((sqlite3 *) m_handle),
                        sqlite3_errmsg((sqlite3 *) m_handle), &m_error);
    return false;
#else  //SQLITE_HAS_CODEC
    Error::ReportSQLite(m_tag, path, Error::HandleOperation::SetCipherKey,
                        SQLITE_MISUSE, SQLITE_MISUSE,
                        "[sqlite3_key] is not supported for current config",
                        &m_error);
    return false;
#endif //SQLITE_HAS_CODEC
}
Beispiel #23
0
NetPhoneConfig * np_config_new(const char *filename){
	NetPhoneConfig *npconfig=np_new0(NetPhoneConfig,1);
	if (filename!=NULL){
		npconfig->filename=strdup(filename);
#ifdef HAVE_SQLITE3
		npconfig->db = NULL;
		if (sqlite3_open(filename,&npconfig->db) == SQLITE_OK){
			sqlite3_key(npconfig->db,SQLITE3_KEY,SQLITE3_KEY_LEN);

			if(!sqlite3_table_new(npconfig->db));
				np_config_parse(npconfig);

			sqlite3_close(npconfig->db);
		}else{
			//np_warning("Can't open database: %s\n", sqlite3_errmsg(npconfig->db));
		}
		npconfig->db = NULL;
#else
#ifdef _MSC_VER
		npconfig->file=fopen(npconfig->filename,"a+b");
#else
		npconfig->file=fopen(npconfig->filename,"rw");
#endif // _MSC_VER
		if (npconfig->file!=NULL){
			np_config_parse(npconfig);
			fclose(npconfig->file);

			/* make existing configuration files non-group/world-accessible */
			//if (chmod(filename, S_IRUSR | S_IWUSR) == -1)
			//	np_warning("unable to correct permissions on "
			//	  	  "configuration file: %s",
			//		   strerror(errno));
			npconfig->file=NULL;
			npconfig->modified=0;
		}
#endif // HAVE_SQLITE3

	}
	return npconfig;
}
      connection_handle::connection_handle(connection_config conf) : config(conf), sqlite(nullptr)
      {
        auto rc = sqlite3_open_v2(conf.path_to_database.c_str(), &sqlite, conf.flags,
                                  conf.vfs.empty() ? nullptr : conf.vfs.c_str());
        if (rc != SQLITE_OK)
        {
          const std::string msg = sqlite3_errmsg(sqlite);
          sqlite3_close(sqlite);
          throw sqlpp::exception("Sqlite3 error: Can't open database: " + msg);
        }
#ifdef SQLITE_HAS_CODEC
        if (conf.password.size()>0)
        {
          int ret = sqlite3_key(sqlite, conf.password.data(),conf.password.size()+1);
          if (ret!=SQLITE_OK)
          {
            const std::string msg = sqlite3_errmsg(sqlite);
            sqlite3_close(sqlite);
            throw sqlpp::exception("Sqlite3 error: Can't set password to database: " + msg);
          }
        }
#endif
      }
Beispiel #25
0
static int sqlcipher_check_connection(const char *filename, char *key, int key_sz, char *sql, int *user_version) {
  int rc;
  sqlite3 *db = NULL;
  sqlite3_stmt *statement = NULL;
  char *query_user_version = "PRAGMA user_version;";
  
  rc = sqlite3_open(filename, &db);
  if(rc != SQLITE_OK){
    goto cleanup;
  }
  rc = sqlite3_key(db, key, key_sz);
  if(rc != SQLITE_OK){
    goto cleanup;
  }
  rc = sqlite3_exec(db, sql, NULL, NULL, NULL);
  if(rc != SQLITE_OK){
    goto cleanup;
  }
  rc = sqlite3_prepare(db, query_user_version, -1, &statement, NULL);
  if(rc != SQLITE_OK){
    goto cleanup;
  }
  rc = sqlite3_step(statement);
  if(rc == SQLITE_ROW){
    *user_version = sqlite3_column_int(statement, 0);
    rc = SQLITE_OK;
  }
  
cleanup:
  if(statement){
    sqlite3_finalize(statement);
  }
  if(db){
    sqlite3_close(db);
  }
  return rc;
}
Beispiel #26
0
int sqlite3_key_v2(sqlite3 *db, const char *zDbName, const void *zKey, int nKey)
{
  /* The key is only set for the main database, not the temp database  */
  return sqlite3_key(db, zKey, nKey);
}
Beispiel #27
0
int main(int argc, char** argv)
{
    sqlite3 * db;
    const char * key = "testkey";
    const char * dbname = "./testdb";
    int keylen = 7;
    char * error=0;

    fprintf(stderr, "Creating Database \"%s\"\n", dbname);
    int rc = sqlite3_open(dbname, &db);
    if (rc != SQLITE_OK) {
        fprintf(stderr, "Can't open/create database: %s\n", sqlite3_errmsg(db));
        return 1;
    }

    fprintf(stderr, "Keying Database with key \"%s\"\n", key);
    rc = sqlite3_key(db, key, keylen);
    if (rc != SQLITE_OK) {
        fprintf(stderr, "Can't key database: %s\n", sqlite3_errmsg(db));
        return 1;
    }

    fprintf(stderr, "Creating table \"test\"\n");
    rc = sqlite3_exec(db, SQL::CREATE_TABLE_TEST, 0, 0, &error);
    if (rc != SQLITE_OK) {
        fprintf(stderr, "SQL error: %s\n", error);
        return 1;
    }

    fprintf(stderr, "Creating table \"test2\"\n");
    rc = sqlite3_exec(db, SQL::CREATE_TABLE_TEST2, 0, 0, &error);
    if (rc != SQLITE_OK) {
        fprintf(stderr, "SQL error: %s\n", error);
        return 1;
    }

    fprintf(stderr, "Inserting into table \"test\"\n");
    rc = sqlite3_exec(db, SQL::INSERT_INTO_TEST, 0, 0, &error);
    if (rc != SQLITE_OK) {
        fprintf(stderr, "SQL error: %s\n", error);
        return 1;
    }

    fprintf(stderr, "Inserting into table \"test2\"\n");
    rc = sqlite3_exec(db, SQL::INSERT_INTO_TEST2, 0, 0, &error);
    if (rc != SQLITE_OK) {
        fprintf(stderr, "SQL error: %s\n", error);
        return 1;
    }

    fprintf(stderr, "Closing Database \"%s\"\n", dbname);
    sqlite3_close(db);

    fprintf(stderr, "Opening Database \"%s\"\n", dbname);
    rc = sqlite3_open(dbname, &db);
    if (rc != SQLITE_OK) {
        fprintf(stderr, "Can't open/create database: %s\n", sqlite3_errmsg(db));
        return 1;
    }

    fprintf(stderr, "Keying Database with key \"%s\"\n", key);
    rc = sqlite3_key(db, key, keylen);
    if (rc != SQLITE_OK) {
        fprintf(stderr, "Can't key database: %s\n", sqlite3_errmsg(db));
        return 1;
    }

    fprintf(stderr, "Selecting all from test\n");
    rc = sqlite3_exec(db, SQL::SELECT_FROM_TEST, callback, 0, &error);
    if (rc != SQLITE_OK) {
        fprintf(stderr, "SQL error: %s\n", error);
        return 1;
    }

    fprintf(stderr, "Selecting all from test2\n");
    rc = sqlite3_exec(db, SQL::SELECT_FROM_TEST2, callback, 0, &error);
    if (rc != SQLITE_OK) {
        fprintf(stderr, "SQL error: %s\n", error);
        return 1;
    }

    fprintf(stderr, "Closing Database \"%s\"\n", dbname);
    sqlite3_close(db);

    fprintf(stderr, "All Seems Good \n");
    return 0;
}
int main(int argc, char* argv[])
{
    sqlite3 *db;
    char *zErrMsg = 0;
    int  rc;
    char *sql;

    /* Open database */
    rc = sqlite3_open("test.db", &db);
    if( rc ){
        fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
        exit(0);
    }else{
        fprintf(stdout, "Opened database successfully\n");
    }

    rc = sqlite3_key(db, passwd, strlen(passwd));

    if( rc ){
        fprintf(stderr, "Can't encrypt database: %s\n", sqlite3_errmsg(db));
        exit(0);
    }else{
        fprintf(stdout, "Encrypt database successfully\n");
    }

    /* Create SQL statement */
    sql = "CREATE TABLE IF NOT EXISTS COMPANY ("  \
           "ID INT PRIMARY KEY     NOT NULL," \
           "NAME           TEXT    NOT NULL," \
           "AGE            INT     NOT NULL," \
           "ADDRESS        CHAR(50)," \
           "SALARY         REAL );"; //Create table

    /* Execute SQL statement */
    rc = sqlite3_exec(db, sql, callback, 0, &zErrMsg);
    if( rc != SQLITE_OK ){
        fprintf(stderr, "SQL error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
    }else{
        fprintf(stdout, "Table created successfully\n");
    }


    sql = "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) "  \
           "VALUES (1, 'Paul', 32, 'California', 20000.00 ); " \
           "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) "  \
           "VALUES (2, 'Allen', 25, 'Texas', 15000.00 ); "     \
           "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)" \
           "VALUES (3, 'Teddy', 23, 'Norway', 20000.00 );" \
           "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)" \
           "VALUES (4, 'Mark', 25, 'Rich-Mond ', 65000.00 );";  //Insert data

    /* Execute SQL statement */
    rc = sqlite3_exec(db, sql, callback, 0, &zErrMsg);
    if( rc != SQLITE_OK ){
        fprintf(stderr, "SQL error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
    }else{
        fprintf(stdout, "Records created successfully\n");
    }


    /* Create SQL statement */
    sql = "SELECT * from COMPANY"; //Select data

    /* Execute SQL statement */
    const char* data = "Callback function called";
    rc = sqlite3_exec(db, sql, callback, (void*)data, &zErrMsg);
    if( rc != SQLITE_OK ){
        fprintf(stderr, "SQL error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
    }else{
        fprintf(stdout, "Operation done successfully\n");
    }

    sqlite3_close(db);

    return 0;
}
Beispiel #29
0
/*
** Process a pragma statement.  
**
** Pragmas are of this form:
**
**      PRAGMA [database.]id [= value]
**
** The identifier might also be a string.  The value is a string, and
** identifier, or a number.  If minusFlag is true, then the value is
** a number that was preceded by a minus sign.
**
** If the left side is "database.id" then pId1 is the database name
** and pId2 is the id.  If the left side is just "id" then pId1 is the
** id and pId2 is any empty string.
*/
void sqlite3Pragma(
  Parse *pParse, 
  Token *pId1,        /* First part of [database.]id field */
  Token *pId2,        /* Second part of [database.]id field, or NULL */
  Token *pValue,      /* Token for <value>, or NULL */
  int minusFlag       /* True if a '-' sign preceded <value> */
){
  char *zLeft = 0;       /* Nul-terminated UTF-8 string <id> */
  char *zRight = 0;      /* Nul-terminated UTF-8 string <value>, or NULL */
  const char *zDb = 0;   /* The database name */
  Token *pId;            /* Pointer to <id> token */
  int iDb;               /* Database index for <database> */
  sqlite3 *db = pParse->db;
  Db *pDb;
  Vdbe *v = sqlite3GetVdbe(pParse);
  if( v==0 ) return;

  /* Interpret the [database.] part of the pragma statement. iDb is the
  ** index of the database this pragma is being applied to in db.aDb[]. */
  iDb = sqlite3TwoPartName(pParse, pId1, pId2, &pId);
  if( iDb<0 ) return;
  pDb = &db->aDb[iDb];

  zLeft = sqlite3NameFromToken(pId);
  if( !zLeft ) return;
  if( minusFlag ){
    zRight = sqlite3MPrintf("-%T", pValue);
  }else{
    zRight = sqlite3NameFromToken(pValue);
  }

  zDb = ((iDb>0)?pDb->zName:0);
  if( sqlite3AuthCheck(pParse, SQLITE_PRAGMA, zLeft, zRight, zDb) ){
    goto pragma_out;
  }
 
#ifndef SQLITE_OMIT_PAGER_PRAGMAS
  /*
  **  PRAGMA [database.]default_cache_size
  **  PRAGMA [database.]default_cache_size=N
  **
  ** The first form reports the current persistent setting for the
  ** page cache size.  The value returned is the maximum number of
  ** pages in the page cache.  The second form sets both the current
  ** page cache size value and the persistent page cache size value
  ** stored in the database file.
  **
  ** The default cache size is stored in meta-value 2 of page 1 of the
  ** database file.  The cache size is actually the absolute value of
  ** this memory location.  The sign of meta-value 2 determines the
  ** synchronous setting.  A negative value means synchronous is off
  ** and a positive value means synchronous is on.
  */
  if( sqlite3StrICmp(zLeft,"default_cache_size")==0 ){
    static const VdbeOpList getCacheSize[] = {
      { OP_ReadCookie,  0, 2,        0},  /* 0 */
      { OP_AbsValue,    0, 0,        0},
      { OP_Dup,         0, 0,        0},
      { OP_Integer,     0, 0,        0},
      { OP_Ne,          0, 6,        0},
      { OP_Integer,     0, 0,        0},  /* 5 */
      { OP_Callback,    1, 0,        0},
    };
    int addr;
    if( sqlite3ReadSchema(pParse) ) goto pragma_out;
    if( !zRight ){
      sqlite3VdbeSetNumCols(v, 1);
      sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cache_size", P3_STATIC);
      addr = sqlite3VdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize);
      sqlite3VdbeChangeP1(v, addr, iDb);
      sqlite3VdbeChangeP1(v, addr+5, MAX_PAGES);
    }else{
      int size = atoi(zRight);
      if( size<0 ) size = -size;
      sqlite3BeginWriteOperation(pParse, 0, iDb);
      sqlite3VdbeAddOp(v, OP_Integer, size, 0);
      sqlite3VdbeAddOp(v, OP_ReadCookie, iDb, 2);
      addr = sqlite3VdbeAddOp(v, OP_Integer, 0, 0);
      sqlite3VdbeAddOp(v, OP_Ge, 0, addr+3);
      sqlite3VdbeAddOp(v, OP_Negative, 0, 0);
      sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 2);
      pDb->pSchema->cache_size = size;
      sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size);
    }
  }else

  /*
  **  PRAGMA [database.]page_size
  **  PRAGMA [database.]page_size=N
  **
  ** The first form reports the current setting for the
  ** database page size in bytes.  The second form sets the
  ** database page size value.  The value can only be set if
  ** the database has not yet been created.
  */
  if( sqlite3StrICmp(zLeft,"page_size")==0 ){
    Btree *pBt = pDb->pBt;
    if( !zRight ){
      int size = pBt ? sqlite3BtreeGetPageSize(pBt) : 0;
      returnSingleInt(pParse, "page_size", size);
    }else{
      sqlite3BtreeSetPageSize(pBt, atoi(zRight), -1);
    }
  }else
#endif /* SQLITE_OMIT_PAGER_PRAGMAS */

  /*
  **  PRAGMA [database.]auto_vacuum
  **  PRAGMA [database.]auto_vacuum=N
  **
  ** Get or set the (boolean) value of the database 'auto-vacuum' parameter.
  */
#ifndef SQLITE_OMIT_AUTOVACUUM
  if( sqlite3StrICmp(zLeft,"auto_vacuum")==0 ){
    Btree *pBt = pDb->pBt;
    if( !zRight ){
      int auto_vacuum = 
          pBt ? sqlite3BtreeGetAutoVacuum(pBt) : SQLITE_DEFAULT_AUTOVACUUM;
      returnSingleInt(pParse, "auto_vacuum", auto_vacuum);
    }else{
      sqlite3BtreeSetAutoVacuum(pBt, getBoolean(zRight));
    }
  }else
#endif

#ifndef SQLITE_OMIT_PAGER_PRAGMAS
  /*
  **  PRAGMA [database.]cache_size
  **  PRAGMA [database.]cache_size=N
  **
  ** The first form reports the current local setting for the
  ** page cache size.  The local setting can be different from
  ** the persistent cache size value that is stored in the database
  ** file itself.  The value returned is the maximum number of
  ** pages in the page cache.  The second form sets the local
  ** page cache size value.  It does not change the persistent
  ** cache size stored on the disk so the cache size will revert
  ** to its default value when the database is closed and reopened.
  ** N should be a positive integer.
  */
  if( sqlite3StrICmp(zLeft,"cache_size")==0 ){
    if( sqlite3ReadSchema(pParse) ) goto pragma_out;
    if( !zRight ){
      returnSingleInt(pParse, "cache_size", pDb->pSchema->cache_size);
    }else{
      int size = atoi(zRight);
      if( size<0 ) size = -size;
      pDb->pSchema->cache_size = size;
      sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size);
    }
  }else

  /*
  **   PRAGMA temp_store
  **   PRAGMA temp_store = "default"|"memory"|"file"
  **
  ** Return or set the local value of the temp_store flag.  Changing
  ** the local value does not make changes to the disk file and the default
  ** value will be restored the next time the database is opened.
  **
  ** Note that it is possible for the library compile-time options to
  ** override this setting
  */
  if( sqlite3StrICmp(zLeft, "temp_store")==0 ){
    if( !zRight ){
      returnSingleInt(pParse, "temp_store", db->temp_store);
    }else{
      changeTempStorage(pParse, zRight);
    }
  }else

  /*
  **   PRAGMA temp_store_directory
  **   PRAGMA temp_store_directory = ""|"directory_name"
  **
  ** Return or set the local value of the temp_store_directory flag.  Changing
  ** the value sets a specific directory to be used for temporary files.
  ** Setting to a null string reverts to the default temporary directory search.
  ** If temporary directory is changed, then invalidateTempStorage.
  **
  */
  if( sqlite3StrICmp(zLeft, "temp_store_directory")==0 ){
    if( !zRight ){
      if( sqlite3_temp_directory ){
        sqlite3VdbeSetNumCols(v, 1);
        sqlite3VdbeSetColName(v, 0, COLNAME_NAME, 
            "temp_store_directory", P3_STATIC);
        sqlite3VdbeOp3(v, OP_String8, 0, 0, sqlite3_temp_directory, 0);
        sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
      }
    }else{
      if( zRight[0] && !sqlite3OsIsDirWritable(zRight) ){
        sqlite3ErrorMsg(pParse, "not a writable directory");
        goto pragma_out;
      }
      if( TEMP_STORE==0
       || (TEMP_STORE==1 && db->temp_store<=1)
       || (TEMP_STORE==2 && db->temp_store==1)
      ){
        invalidateTempStorage(pParse);
      }
      sqliteFree(sqlite3_temp_directory);
      if( zRight[0] ){
        sqlite3_temp_directory = zRight;
        zRight = 0;
      }else{
        sqlite3_temp_directory = 0;
      }
    }
  }else

  /*
  **   PRAGMA [database.]synchronous
  **   PRAGMA [database.]synchronous=OFF|ON|NORMAL|FULL
  **
  ** Return or set the local value of the synchronous flag.  Changing
  ** the local value does not make changes to the disk file and the
  ** default value will be restored the next time the database is
  ** opened.
  */
  if( sqlite3StrICmp(zLeft,"synchronous")==0 ){
    if( sqlite3ReadSchema(pParse) ) goto pragma_out;
    if( !zRight ){
      returnSingleInt(pParse, "synchronous", pDb->safety_level-1);
    }else{
      if( !db->autoCommit ){
        sqlite3ErrorMsg(pParse, 
            "Safety level may not be changed inside a transaction");
      }else{
        pDb->safety_level = getSafetyLevel(zRight)+1;
      }
    }
  }else
#endif /* SQLITE_OMIT_PAGER_PRAGMAS */

#ifndef SQLITE_OMIT_FLAG_PRAGMAS
  if( flagPragma(pParse, zLeft, zRight) ){
    /* The flagPragma() subroutine also generates any necessary code
    ** there is nothing more to do here */
  }else
#endif /* SQLITE_OMIT_FLAG_PRAGMAS */

#ifndef SQLITE_OMIT_SCHEMA_PRAGMAS
  /*
  **   PRAGMA table_info(<table>)
  **
  ** Return a single row for each column of the named table. The columns of
  ** the returned data set are:
  **
  ** cid:        Column id (numbered from left to right, starting at 0)
  ** name:       Column name
  ** type:       Column declaration type.
  ** notnull:    True if 'NOT NULL' is part of column declaration
  ** dflt_value: The default value for the column, if any.
  */
  if( sqlite3StrICmp(zLeft, "table_info")==0 && zRight ){
    Table *pTab;
    if( sqlite3ReadSchema(pParse) ) goto pragma_out;
    pTab = sqlite3FindTable(db, zRight, zDb);
    if( pTab ){
      int i;
      Column *pCol;
      sqlite3VdbeSetNumCols(v, 6);
      sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cid", P3_STATIC);
      sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", P3_STATIC);
      sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "type", P3_STATIC);
      sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "notnull", P3_STATIC);
      sqlite3VdbeSetColName(v, 4, COLNAME_NAME, "dflt_value", P3_STATIC);
      sqlite3VdbeSetColName(v, 5, COLNAME_NAME, "pk", P3_STATIC);
      sqlite3ViewGetColumnNames(pParse, pTab);
      for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
        sqlite3VdbeAddOp(v, OP_Integer, i, 0);
        sqlite3VdbeOp3(v, OP_String8, 0, 0, pCol->zName, 0);
        sqlite3VdbeOp3(v, OP_String8, 0, 0,
           pCol->zType ? pCol->zType : "numeric", 0);
        sqlite3VdbeAddOp(v, OP_Integer, pCol->notNull, 0);
        sqlite3ExprCode(pParse, pCol->pDflt);
        sqlite3VdbeAddOp(v, OP_Integer, pCol->isPrimKey, 0);
        sqlite3VdbeAddOp(v, OP_Callback, 6, 0);
      }
    }
  }else

  if( sqlite3StrICmp(zLeft, "index_info")==0 && zRight ){
    Index *pIdx;
    Table *pTab;
    if( sqlite3ReadSchema(pParse) ) goto pragma_out;
    pIdx = sqlite3FindIndex(db, zRight, zDb);
    if( pIdx ){
      int i;
      pTab = pIdx->pTable;
      sqlite3VdbeSetNumCols(v, 3);
      sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seqno", P3_STATIC);
      sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "cid", P3_STATIC);
      sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "name", P3_STATIC);
      for(i=0; i<pIdx->nColumn; i++){
        int cnum = pIdx->aiColumn[i];
        sqlite3VdbeAddOp(v, OP_Integer, i, 0);
        sqlite3VdbeAddOp(v, OP_Integer, cnum, 0);
        assert( pTab->nCol>cnum );
        sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->aCol[cnum].zName, 0);
        sqlite3VdbeAddOp(v, OP_Callback, 3, 0);
      }
    }
  }else

  if( sqlite3StrICmp(zLeft, "index_list")==0 && zRight ){
    Index *pIdx;
    Table *pTab;
    if( sqlite3ReadSchema(pParse) ) goto pragma_out;
    pTab = sqlite3FindTable(db, zRight, zDb);
    if( pTab ){
      v = sqlite3GetVdbe(pParse);
      pIdx = pTab->pIndex;
      if( pIdx ){
        int i = 0; 
        sqlite3VdbeSetNumCols(v, 3);
        sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", P3_STATIC);
        sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", P3_STATIC);
        sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", P3_STATIC);
        while(pIdx){
          sqlite3VdbeAddOp(v, OP_Integer, i, 0);
          sqlite3VdbeOp3(v, OP_String8, 0, 0, pIdx->zName, 0);
          sqlite3VdbeAddOp(v, OP_Integer, pIdx->onError!=OE_None, 0);
          sqlite3VdbeAddOp(v, OP_Callback, 3, 0);
          ++i;
          pIdx = pIdx->pNext;
        }
      }
    }
  }else

  if( sqlite3StrICmp(zLeft, "database_list")==0 ){
    int i;
    if( sqlite3ReadSchema(pParse) ) goto pragma_out;
    sqlite3VdbeSetNumCols(v, 3);
    sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", P3_STATIC);
    sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", P3_STATIC);
    sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "file", P3_STATIC);
    for(i=0; i<db->nDb; i++){
      if( db->aDb[i].pBt==0 ) continue;
      assert( db->aDb[i].zName!=0 );
      sqlite3VdbeAddOp(v, OP_Integer, i, 0);
      sqlite3VdbeOp3(v, OP_String8, 0, 0, db->aDb[i].zName, 0);
      sqlite3VdbeOp3(v, OP_String8, 0, 0,
           sqlite3BtreeGetFilename(db->aDb[i].pBt), 0);
      sqlite3VdbeAddOp(v, OP_Callback, 3, 0);
    }
  }else

  if( sqlite3StrICmp(zLeft, "collation_list")==0 ){
    int i = 0;
    HashElem *p;
    sqlite3VdbeSetNumCols(v, 2);
    sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", P3_STATIC);
    sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", P3_STATIC);
    for(p=sqliteHashFirst(&db->aCollSeq); p; p=sqliteHashNext(p)){
      CollSeq *pColl = (CollSeq *)sqliteHashData(p);
      sqlite3VdbeAddOp(v, OP_Integer, i++, 0);
      sqlite3VdbeOp3(v, OP_String8, 0, 0, pColl->zName, 0);
      sqlite3VdbeAddOp(v, OP_Callback, 2, 0);
    }
  }else
#endif /* SQLITE_OMIT_SCHEMA_PRAGMAS */

#ifndef SQLITE_OMIT_FOREIGN_KEY
  if( sqlite3StrICmp(zLeft, "foreign_key_list")==0 && zRight ){
    FKey *pFK;
    Table *pTab;
    if( sqlite3ReadSchema(pParse) ) goto pragma_out;
    pTab = sqlite3FindTable(db, zRight, zDb);
    if( pTab ){
      v = sqlite3GetVdbe(pParse);
      pFK = pTab->pFKey;
      if( pFK ){
        int i = 0; 
        sqlite3VdbeSetNumCols(v, 5);
        sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "id", P3_STATIC);
        sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "seq", P3_STATIC);
        sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "table", P3_STATIC);
        sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "from", P3_STATIC);
        sqlite3VdbeSetColName(v, 4, COLNAME_NAME, "to", P3_STATIC);
        while(pFK){
          int j;
          for(j=0; j<pFK->nCol; j++){
            char *zCol = pFK->aCol[j].zCol;
            sqlite3VdbeAddOp(v, OP_Integer, i, 0);
            sqlite3VdbeAddOp(v, OP_Integer, j, 0);
            sqlite3VdbeOp3(v, OP_String8, 0, 0, pFK->zTo, 0);
            sqlite3VdbeOp3(v, OP_String8, 0, 0,
                             pTab->aCol[pFK->aCol[j].iFrom].zName, 0);
            sqlite3VdbeOp3(v, zCol ? OP_String8 : OP_Null, 0, 0, zCol, 0);
            sqlite3VdbeAddOp(v, OP_Callback, 5, 0);
          }
          ++i;
          pFK = pFK->pNextFrom;
        }
      }
    }
  }else
#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */

#ifndef NDEBUG
  if( sqlite3StrICmp(zLeft, "parser_trace")==0 ){
    extern void sqlite3ParserTrace(FILE*, char *);
    if( zRight ){
      if( getBoolean(zRight) ){
        sqlite3ParserTrace(stderr, "parser: ");
      }else{
        sqlite3ParserTrace(0, 0);
      }
    }
  }else
#endif

  /* Reinstall the LIKE and GLOB functions.  The variant of LIKE
  ** used will be case sensitive or not depending on the RHS.
  */
  if( sqlite3StrICmp(zLeft, "case_sensitive_like")==0 ){
    if( zRight ){
      sqlite3RegisterLikeFunctions(db, getBoolean(zRight));
    }
  }else

#ifndef SQLITE_OMIT_INTEGRITY_CHECK
  if( sqlite3StrICmp(zLeft, "integrity_check")==0 ){
    int i, j, addr;

    /* Code that appears at the end of the integrity check.  If no error
    ** messages have been generated, output OK.  Otherwise output the
    ** error message
    */
    static const VdbeOpList endCode[] = {
      { OP_MemLoad,     0, 0,        0},
      { OP_Integer,     0, 0,        0},
      { OP_Ne,          0, 0,        0},    /* 2 */
      { OP_String8,     0, 0,        "ok"},
      { OP_Callback,    1, 0,        0},
    };

    /* Initialize the VDBE program */
    if( sqlite3ReadSchema(pParse) ) goto pragma_out;
    sqlite3VdbeSetNumCols(v, 1);
    sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "integrity_check", P3_STATIC);
    sqlite3VdbeAddOp(v, OP_MemInt, 0, 0);  /* Initialize error count to 0 */

    /* Do an integrity check on each database file */
    for(i=0; i<db->nDb; i++){
      HashElem *x;
      Hash *pTbls;
      int cnt = 0;

      if( OMIT_TEMPDB && i==1 ) continue;

      sqlite3CodeVerifySchema(pParse, i);

      /* Do an integrity check of the B-Tree
      */
      pTbls = &db->aDb[i].pSchema->tblHash;
      for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
        Table *pTab = sqliteHashData(x);
        Index *pIdx;
        sqlite3VdbeAddOp(v, OP_Integer, pTab->tnum, 0);
        cnt++;
        for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
          sqlite3VdbeAddOp(v, OP_Integer, pIdx->tnum, 0);
          cnt++;
        }
      }
      assert( cnt>0 );
      sqlite3VdbeAddOp(v, OP_IntegrityCk, cnt, i);
      sqlite3VdbeAddOp(v, OP_Dup, 0, 1);
      addr = sqlite3VdbeOp3(v, OP_String8, 0, 0, "ok", P3_STATIC);
      sqlite3VdbeAddOp(v, OP_Eq, 0, addr+7);
      sqlite3VdbeOp3(v, OP_String8, 0, 0,
         sqlite3MPrintf("*** in database %s ***\n", db->aDb[i].zName),
         P3_DYNAMIC);
      sqlite3VdbeAddOp(v, OP_Pull, 1, 0);
      sqlite3VdbeAddOp(v, OP_Concat, 0, 1);
      sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
      sqlite3VdbeAddOp(v, OP_MemIncr, 1, 0);

      /* Make sure all the indices are constructed correctly.
      */
      sqlite3CodeVerifySchema(pParse, i);
      for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
        Table *pTab = sqliteHashData(x);
        Index *pIdx;
        int loopTop;

        if( pTab->pIndex==0 ) continue;
        sqlite3OpenTableAndIndices(pParse, pTab, 1, OP_OpenRead);
        sqlite3VdbeAddOp(v, OP_MemInt, 0, 1);
        loopTop = sqlite3VdbeAddOp(v, OP_Rewind, 1, 0);
        sqlite3VdbeAddOp(v, OP_MemIncr, 1, 1);
        for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
          int jmp2;
          static const VdbeOpList idxErr[] = {
            { OP_MemIncr,     1,  0,  0},
            { OP_String8,     0,  0,  "rowid "},
            { OP_Rowid,       1,  0,  0},
            { OP_String8,     0,  0,  " missing from index "},
            { OP_String8,     0,  0,  0},    /* 4 */
            { OP_Concat,      2,  0,  0},
            { OP_Callback,    1,  0,  0},
          };
          sqlite3GenerateIndexKey(v, pIdx, 1);
          jmp2 = sqlite3VdbeAddOp(v, OP_Found, j+2, 0);
          addr = sqlite3VdbeAddOpList(v, ArraySize(idxErr), idxErr);
          sqlite3VdbeChangeP3(v, addr+4, pIdx->zName, P3_STATIC);
          sqlite3VdbeJumpHere(v, jmp2);
        }
        sqlite3VdbeAddOp(v, OP_Next, 1, loopTop+1);
        sqlite3VdbeJumpHere(v, loopTop);
        for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
          static const VdbeOpList cntIdx[] = {
             { OP_MemInt,       0,  2,  0},
             { OP_Rewind,       0,  0,  0},  /* 1 */
             { OP_MemIncr,      1,  2,  0},
             { OP_Next,         0,  0,  0},  /* 3 */
             { OP_MemLoad,      1,  0,  0},
             { OP_MemLoad,      2,  0,  0},
             { OP_Eq,           0,  0,  0},  /* 6 */
             { OP_MemIncr,      1,  0,  0},
             { OP_String8,      0,  0,  "wrong # of entries in index "},
             { OP_String8,      0,  0,  0},  /* 9 */
             { OP_Concat,       0,  0,  0},
             { OP_Callback,     1,  0,  0},
          };
          if( pIdx->tnum==0 ) continue;
          addr = sqlite3VdbeAddOpList(v, ArraySize(cntIdx), cntIdx);
          sqlite3VdbeChangeP1(v, addr+1, j+2);
          sqlite3VdbeChangeP2(v, addr+1, addr+4);
          sqlite3VdbeChangeP1(v, addr+3, j+2);
          sqlite3VdbeChangeP2(v, addr+3, addr+2);
          sqlite3VdbeJumpHere(v, addr+6);
          sqlite3VdbeChangeP3(v, addr+9, pIdx->zName, P3_STATIC);
        }
      } 
    }
    addr = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode);
    sqlite3VdbeJumpHere(v, addr+2);
  }else
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */

#ifndef SQLITE_OMIT_UTF16
  /*
  **   PRAGMA encoding
  **   PRAGMA encoding = "utf-8"|"utf-16"|"utf-16le"|"utf-16be"
  **
  ** In it's first form, this pragma returns the encoding of the main
  ** database. If the database is not initialized, it is initialized now.
  **
  ** The second form of this pragma is a no-op if the main database file
  ** has not already been initialized. In this case it sets the default
  ** encoding that will be used for the main database file if a new file
  ** is created. If an existing main database file is opened, then the
  ** default text encoding for the existing database is used.
  ** 
  ** In all cases new databases created using the ATTACH command are
  ** created to use the same default text encoding as the main database. If
  ** the main database has not been initialized and/or created when ATTACH
  ** is executed, this is done before the ATTACH operation.
  **
  ** In the second form this pragma sets the text encoding to be used in
  ** new database files created using this database handle. It is only
  ** useful if invoked immediately after the main database i
  */
  if( sqlite3StrICmp(zLeft, "encoding")==0 ){
    static struct EncName {
      char *zName;
      u8 enc;
    } encnames[] = {
      { "UTF-8",    SQLITE_UTF8        },
      { "UTF8",     SQLITE_UTF8        },
      { "UTF-16le", SQLITE_UTF16LE     },
      { "UTF16le",  SQLITE_UTF16LE     },
      { "UTF-16be", SQLITE_UTF16BE     },
      { "UTF16be",  SQLITE_UTF16BE     },
      { "UTF-16",   0 /* Filled in at run-time */ },
      { "UTF16",    0 /* Filled in at run-time */ },
      { 0, 0 }
    };
    struct EncName *pEnc;
    encnames[6].enc = encnames[7].enc = SQLITE_UTF16NATIVE;
    if( !zRight ){    /* "PRAGMA encoding" */
      if( sqlite3ReadSchema(pParse) ) goto pragma_out;
      sqlite3VdbeSetNumCols(v, 1);
      sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "encoding", P3_STATIC);
      sqlite3VdbeAddOp(v, OP_String8, 0, 0);
      for(pEnc=&encnames[0]; pEnc->zName; pEnc++){
        if( pEnc->enc==ENC(pParse->db) ){
          sqlite3VdbeChangeP3(v, -1, pEnc->zName, P3_STATIC);
          break;
        }
      }
      sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
    }else{                        /* "PRAGMA encoding = XXX" */
      /* Only change the value of sqlite.enc if the database handle is not
      ** initialized. If the main database exists, the new sqlite.enc value
      ** will be overwritten when the schema is next loaded. If it does not
      ** already exists, it will be created to use the new encoding value.
      */
      if( 
        !(DbHasProperty(db, 0, DB_SchemaLoaded)) || 
        DbHasProperty(db, 0, DB_Empty) 
      ){
        for(pEnc=&encnames[0]; pEnc->zName; pEnc++){
          if( 0==sqlite3StrICmp(zRight, pEnc->zName) ){
            ENC(pParse->db) = pEnc->enc;
            break;
          }
        }
        if( !pEnc->zName ){
          sqlite3ErrorMsg(pParse, "unsupported encoding: %s", zRight);
        }
      }
    }
  }else
#endif /* SQLITE_OMIT_UTF16 */

#ifndef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
  /*
  **   PRAGMA [database.]schema_version
  **   PRAGMA [database.]schema_version = <integer>
  **
  **   PRAGMA [database.]user_version
  **   PRAGMA [database.]user_version = <integer>
  **
  ** The pragma's schema_version and user_version are used to set or get
  ** the value of the schema-version and user-version, respectively. Both
  ** the schema-version and the user-version are 32-bit signed integers
  ** stored in the database header.
  **
  ** The schema-cookie is usually only manipulated internally by SQLite. It
  ** is incremented by SQLite whenever the database schema is modified (by
  ** creating or dropping a table or index). The schema version is used by
  ** SQLite each time a query is executed to ensure that the internal cache
  ** of the schema used when compiling the SQL query matches the schema of
  ** the database against which the compiled query is actually executed.
  ** Subverting this mechanism by using "PRAGMA schema_version" to modify
  ** the schema-version is potentially dangerous and may lead to program
  ** crashes or database corruption. Use with caution!
  **
  ** The user-version is not used internally by SQLite. It may be used by
  ** applications for any purpose.
  */
  if( sqlite3StrICmp(zLeft, "schema_version")==0 ||
      sqlite3StrICmp(zLeft, "user_version")==0 ){

    int iCookie;   /* Cookie index. 0 for schema-cookie, 6 for user-cookie. */
    if( zLeft[0]=='s' || zLeft[0]=='S' ){
      iCookie = 0;
    }else{
      iCookie = 5;
    }

    if( zRight ){
      /* Write the specified cookie value */
      static const VdbeOpList setCookie[] = {
        { OP_Transaction,    0,  1,  0},    /* 0 */
        { OP_Integer,        0,  0,  0},    /* 1 */
        { OP_SetCookie,      0,  0,  0},    /* 2 */
      };
      int addr = sqlite3VdbeAddOpList(v, ArraySize(setCookie), setCookie);
      sqlite3VdbeChangeP1(v, addr, iDb);
      sqlite3VdbeChangeP1(v, addr+1, atoi(zRight));
      sqlite3VdbeChangeP1(v, addr+2, iDb);
      sqlite3VdbeChangeP2(v, addr+2, iCookie);
    }else{
      /* Read the specified cookie value */
      static const VdbeOpList readCookie[] = {
        { OP_ReadCookie,      0,  0,  0},    /* 0 */
        { OP_Callback,        1,  0,  0}
      };
      int addr = sqlite3VdbeAddOpList(v, ArraySize(readCookie), readCookie);
      sqlite3VdbeChangeP1(v, addr, iDb);
      sqlite3VdbeChangeP2(v, addr, iCookie);
      sqlite3VdbeSetNumCols(v, 1);
    }
  }
#endif /* SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS */

#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
  /*
  ** Report the current state of file logs for all databases
  */
  if( sqlite3StrICmp(zLeft, "lock_status")==0 ){
    static const char *const azLockName[] = {
      "unlocked", "shared", "reserved", "pending", "exclusive"
    };
    int i;
    Vdbe *v = sqlite3GetVdbe(pParse);
    sqlite3VdbeSetNumCols(v, 2);
    sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "database", P3_STATIC);
    sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "status", P3_STATIC);
    for(i=0; i<db->nDb; i++){
      Btree *pBt;
      Pager *pPager;
      if( db->aDb[i].zName==0 ) continue;
      sqlite3VdbeOp3(v, OP_String8, 0, 0, db->aDb[i].zName, P3_STATIC);
      pBt = db->aDb[i].pBt;
      if( pBt==0 || (pPager = sqlite3BtreePager(pBt))==0 ){
        sqlite3VdbeOp3(v, OP_String8, 0, 0, "closed", P3_STATIC);
      }else{
        int j = sqlite3pager_lockstate(pPager);
        sqlite3VdbeOp3(v, OP_String8, 0, 0, 
            (j>=0 && j<=4) ? azLockName[j] : "unknown", P3_STATIC);
      }
      sqlite3VdbeAddOp(v, OP_Callback, 2, 0);
    }
  }else
#endif

#ifdef SQLITE_SSE
  /*
  ** Check to see if the sqlite_statements table exists.  Create it
  ** if it does not.
  */
  if( sqlite3StrICmp(zLeft, "create_sqlite_statement_table")==0 ){
    extern int sqlite3CreateStatementsTable(Parse*);
    sqlite3CreateStatementsTable(pParse);
  }else
#endif

#if SQLITE_HAS_CODEC
  if( sqlite3StrICmp(zLeft, "key")==0 ){
    sqlite3_key(db, zRight, strlen(zRight));
  }else
#endif

  {}

  if( v ){
    /* Code an OP_Expire at the end of each PRAGMA program to cause
    ** the VDBE implementing the pragma to expire. Most (all?) pragmas
    ** are only valid for a single execution.
    */
    sqlite3VdbeAddOp(v, OP_Expire, 1, 0);

    /*
    ** Reset the safety level, in case the fullfsync flag or synchronous
    ** setting changed.
    */
    if( db->autoCommit ){
      sqlite3BtreeSetSafetyLevel(pDb->pBt, pDb->safety_level,
                 (db->flags&SQLITE_FullFSync)!=0);
    }
  }
pragma_out:
  sqliteFree(zLeft);
  sqliteFree(zRight);
}
Beispiel #30
0
/*
** 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;
		p->rc = btreeDeleteEnvironment(p->pDest, p->fullName, 1);
		if (storage == DB_STORE_INMEM && strcmp(p->destName, "temp")
		    != 0)
			home = inmem;
		else
			home = p->fullName;
		p->pDest = p->pDestDb->aDb[p->iDb].pBt;
		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;
		} else {
			p->rc = sqlite3BtreeOpen(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->rc == SQLITE_OK) {
				p->pDestDb->aDb[p->iDb].pSchema =
				    sqlite3SchemaGet(p->pDestDb, p->pDest);
				if (!p->pDestDb->aDb[p->iDb].pSchema)
					p->rc = SQLITE_NOMEM;
			} else
				p->pDestDb->aDb[p->iDb].pSchema = NULL;
		}

		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 = sqlite3BtreeBeginTrans(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))) != 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;
		sqlite3ResetInternalSchema(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);
}