在一个未做加密的数据库上,需要进行数据迁移,迁移到一个加密的数据库上,代码如下:
let oldDBPath = MyDBDataPath.basePath + userId + ".db"
let newDBPath = MyDBDataPath.basePath + userId + "_encryption.db"
let oldDataBase = Database(at: oldDBPath)
self.createTable(dataBase: oldDataBase, tableSubString: "")
self.myDatabase = Database(at: newDBPath)
let password = userId.data(using: .ascii)
self.myDatabase?.setCipher(key: password)
self.myDatabase?.setAutoMigration(enable: true)
// self.myDatabase?.tag = 10599
self.myDatabase?.addMigration(sourcePath: oldDBPath,{ info in
info.sourceTable = info.table + "_encryption"; //配置数据迁移的源表格名
})
self.createTable(dataBase: self.myDatabase, tableSubString: "_encryption")
在迁移的过程中报错: "未能完成操作。(WCDBSwift.WCDBError错误1。)"
使用AI进行分析如下:
根本原因分析
通过深入分析 WCDB 源码,我找到了确切的 bug 原因:
SQLCipher ATTACH 机制问题
从 MigrationInfo.cpp 可以看到:
MigrationDatabaseInfo::MigrationDatabaseInfo(...) {
m_statementForAttachingSchema = StatementAttach().attach(m_sourcePath).as(m_schema);
if (!cipher.empty()) {
m_statementForAttachingSchema.key(BindParameter(1)); // 只有cipher非空才添加KEY
}
}
再看 MigratingHandleDecorator.cpp 的 attach 逻辑:
bool MigratingHandleDecorator::attachDatabase(...) {
const Data& cipher = attachInfo->getSourceCipher();
if (!cipher.empty()) {
handleStatement.bindBLOB(cipher); // 只有cipher非空才绑定key
}
succeed = handleStatement.step();
}
而 UnsafeData::empty() 判断逻辑是 m_size == 0。问题链条:
1、你传 sourceCipher: nil → C++ 层 cipher 为空 (size=0)
2、ATTACH 语句变成:ATTACH DATABASE '/old.db' AS 'schema'(没有 KEY 子句)
3、SQLCipher 规则:ATTACH 不指定 KEY 时,使用主数据库的 key 来打开附加数据库
4、你的主数据库(target)是加密的,SQLCipher 用这个密钥去解密未加密的源数据库 → 失败!
正确的 SQL 应该是:
ATTACH DATABASE '/old.db' AS 'schema' KEY ''; -- 空key表示明文
这是 WCDB 2.1.15 版本在"加密目标 + 未加密源"跨库迁移场景下的 bug。
在一个未做加密的数据库上,需要进行数据迁移,迁移到一个加密的数据库上,代码如下:
在迁移的过程中报错: "未能完成操作。(WCDBSwift.WCDBError错误1。)"
使用AI进行分析如下:
根本原因分析
通过深入分析 WCDB 源码,我找到了确切的 bug 原因:
SQLCipher ATTACH 机制问题
从 MigrationInfo.cpp 可以看到:
再看 MigratingHandleDecorator.cpp 的 attach 逻辑:
而 UnsafeData::empty() 判断逻辑是 m_size == 0。问题链条:
1、你传 sourceCipher: nil → C++ 层 cipher 为空 (size=0)
2、ATTACH 语句变成:ATTACH DATABASE '/old.db' AS 'schema'(没有 KEY 子句)
3、SQLCipher 规则:ATTACH 不指定 KEY 时,使用主数据库的 key 来打开附加数据库
4、你的主数据库(target)是加密的,SQLCipher 用这个密钥去解密未加密的源数据库 → 失败!
正确的 SQL 应该是:
ATTACH DATABASE '/old.db' AS 'schema' KEY ''; -- 空key表示明文这是 WCDB 2.1.15 版本在"加密目标 + 未加密源"跨库迁移场景下的 bug。