SQLITE_PRIVATE const char *sqlite3ErrStr(int rc){
static const char* const aMsg[] = {
......
/* SQLITE_NOTADB */ "file is not a database",
......
......
return zErr;
可以分析得知lockBtree()
方法就是产生这个Crash的地方,那么着重对该方法进行一个分析。
** Get a reference to pPage1 of the database file. This will
** also acquire a readlock on that file.
** SQLITE_OK is returned on success. If the file is not a
** well-formed database file, then SQLITE_CORRUPT is returned.
** SQLITE_BUSY is returned if the database is locked. SQLITE_NOMEM
** is returned if we run out of memory.
static int lockBtree(BtShared *pBt){
int rc; /* Result code from subfunctions */
MemPage *pPage1; /* Page 1 of the database file */
u32 nPage; /* Number of pages in the database */
u32 nPageFile = 0; /* Number of pages in the database file */
u32 nPageHeader; /* Number of pages in the database according to hdr */
/* Do some checking to help insure the file we opened really is
** a valid database file.
nPage = nPageHeader = get4byte(28+(u8*)pPage1->aData);
sqlite3PagerPagecount(pBt->pPager, (int*)&nPageFile);
if( nPage==0 || memcmp(24+(u8*)pPage1->aData, 92+(u8*)pPage1->aData,4)!=0 ){
nPage = nPageFile;
if( nPage>0 ){
u32 pageSize;
u32 usableSize;
u8 *page1 = pPage1->aData;
rc = SQLITE_NOTADB;
......
#ifdef SQLITE_OMIT_WAL
......
#else
if( page1[18]>2 ){
pBt->btsFlags |= BTS_READ_ONLY;
if( page1[19]>2 ){
goto page1_init_failed;
/* If the write version is set to 2, this database should be accessed
** in WAL mode. If the log is not already open, open it now. Then
** return SQLITE_OK and return without populating BtShared.pPage1.
** The caller detects this and calls this function again. This is
** required as the version of page 1 currently in the page1 buffer
** may not be the latest version - there may be a newer one in the log
** file.
if( page1[19]==2 && (pBt->btsFlags & BTS_NO_WAL)==0 ){
int isOpen = 0;
rc = sqlite3PagerOpenWal(pBt->pPager, &isOpen);
if( rc!=SQLITE_OK ){
goto page1_init_failed;
}else{
setDefaultSyncFlag(pBt, SQLITE_DEFAULT_WAL_SYNCHRONOUS+1);
if( isOpen==0 ){
releasePageOne(pPage1);
return SQLITE_OK;
rc = SQLITE_NOTADB;
}else{
setDefaultSyncFlag(pBt, SQLITE_DEFAULT_SYNCHRONOUS+1);
#endif
......
page1_init_failed:
releasePageOne(pPage1);
pBt->pPage1 = 0;
return rc;
我将lockBTree()
中和Crash不相关的逻辑进行了去除,通过分析可以知道,rc
的默认值就是SQLITE_NOTADB
,在随后的逻辑中
通过sqlite3PagerOpenWal()
方法尝试通过WAL的方式打开数据库,但是其结果不为SQLITE_OK
,导致逻辑直接跳向了page1_init_failed
中。
在sqlite3PagerOpenWal()
方法中又后续调用了pagerOpenWal()
等方法,都是WAL的逻辑。
WAL预写式日志(Write-ahead logging,缩写 WAL)是关系数据库系统中用于提供原子性和持久性(ACID属性中的两个)的一系列技术。在使用WAL的系统中,所有的修改在提交之前都要先写入log文件中。
至此,想要解决这个Crash,只需要禁止数据库的WAL模式即可。
- JOURNAL_MODE:https://sqlite.org/pragma.html#pragma_journal_mode
- WAL:https://zh.wikipedia.org/zh-hans/%E9%A2%84%E5%86%99%E5%BC%8F%E6%97%A5%E5%BF%97
- AndroidWAL:https://source.android.com/devices/tech/perf/compatibility-wal
- nativePrepareStatement: https://cs.android.com/android/platform/superproject/+/android-10.0.0_r30:frameworks/base/core/jni/android_database_SQLiteConnection.cpp;l=303;drc=android-10.0.0_r30
- sqlite:https://android.googlesource.com/platform/external/sqlite.git
- https://blog.csdn.net/aasmfox/article/details/8026333
- https://stackoverflow.com/questions/11901460/is-it-possible-to-disable-wal-on-android-sqlite-database
- https://stackoverflow.com/questions/53659206/disabling-sqlite-write-ahead-logging-in-android-pie/53689702
- https://github.com/CoatiSoftware/Sourcetrail
- https://blog.csdn.net/zearot/article/details/51039593
- https://cs.android.com/android/platform/superproject/+/master:external/rust/crates/
- http://sqlite.1065341.n5.nabble.com/sqlite-3-7-2-doesn-t-compile-if-SQLITE-OMIT-WAL-is-defined-td45921.html
- https://www.sqlite.org/src/info/d1ed743b6e
- https://www.sqlite.org/compile.html
title: “Crash: 'SQLiteDatabaseCorruptException: file is encrypted or is not a database’的分析与解决”tags:先说解决方案与结论方案如果使用的Room库,那么需要按照如下方法设置JournalMode:Room.databaseBuilder(context, XXX::class.java, DATABASE_NAME) .setJournalMode(JournalMode.
static String DB_PATH = "/data/data/com.yuzhiyun.chemistry/databases/";
static String DB_NAME = "sqlite3.db";
private SQLiteDatabase db;
this.db = SQLiteDatabase.openDatabase(DB_PATH+...
Unlock Music 音乐解锁
在浏览器中解锁加密的音乐文件。 Unlock
encrypted music
file in the browser.
unlock-music项目是以学习和技术研究的初衷创建的,修改、再分发时请遵循
Unlock Music的CLI版本正在开发中。
我们新建了Telegram群组,欢迎加入!
支持的格式
QQ音乐 (.qmc0/.qmc2/.qmc3/.qmcflac/.qmcogg/)
写入封面图片
Moo音乐格式 ()
QQ音乐Tm格式 (.tm0/.tm2/.tm3/.tm6)
QQ音乐新格式 (实验性支持)
.mflac
网易云音乐格式 (.ncm)
补全ncm的ID3/FlacMeta信息
虾米音乐格式 (.xm) (测试阶段)
酷我音乐格式 (.kwm) (测试阶段)
酷狗音乐格式 (.kgm) ()
问题描述:用户将Domino升级完成之后,当用户试图访问server上的邮箱库时,碰到错误信息“数据库已损坏,无法分配空间”解答:这个错误信息通常意味着数据库损坏,在这种情况下,我们通常要用Fixup/Compact/Updall这几个命令来尝试修复数据库。
1.load fixup -f (这样的参数会强制Fixup检查数据库中的所有文档)
2.load compact...
SQLITE_OK = 0; 返回成功
SQLITE_ERROR = 1; SQL错误或错误的数据库
SQLITE_INTERNAL = 2; An internal logic error in
SQLite
SQLITE_PERM = 3; 拒绝
在这一行后面,接上本文最下面的代码段。
这些代码很长,我不再解释,直接接上去就得了。
唯一要提的是 DeriveKey 函数。这个函数是对密钥的扩展。比如,你要求密钥是128位,即是16字节,但是如果用户只输入 1个字节呢?2个字节呢?或输入50个字节呢?你得对密钥进行扩展,使之符合16字节的要求。
DeriveKey 函数就是做这个扩展的。有人把接收到的密钥求md5,这也是一个办法,因为m
为了搞毕设重新捡起sqlite3,照着《第一行代码-Android》使用adb进行查看,但发现实际使用真机操作起来是真的麻烦!
主要是两个坑:1.root权限;2.sqlite3文件
(1)root权限,我使用的是小米手机4。刚开始网上各种找root工具,发现全部没用。等我针对MI4进行搜的时候,才发现原来小米手机只要刷开发版,在 设置->授权管理 里就有一个ROOT权限管理。(这里安...
经过跟踪定位到sqlite3_prepare_v2()函数,返回错误码为26.
通过查找26的定义为:#define SQLITE_NOTADB 26 /*
File opened that is not a databas
Spring4.0+Hibernate4.2.整合出现java.lang.ClassNotFoundException: org.hibernate.engine.FilterDefinition
23163