fix: v0.7.3 数据正确性与边界窗口收尾 — INSERT 语句级原子(三引擎+Aria PK 批内重复)/ 索引列 IS NULL 恒空 / delete RESTRICT 破坏索引 / queryStream 子查询静默空结果 / ALTER DROP 索引残留 / UNIQUE INDEX 存量校验 / SELECT * 别名投影 / WAL BEGIN/ROLLBACK 事务边界 / aria $in 与级联重复扫描性能 / $and 等值下推 / ANALYZE 索引统计 / React-Vue hooks 生命周期 / 迁移主键兜底 + 58 回归
This commit is contained in:
@@ -184,4 +184,61 @@ describe('migrateFromIndexedDB', () => {
|
||||
.rejects.toThrow('not supported');
|
||||
await target.close();
|
||||
});
|
||||
|
||||
it('无 id 列的旧库:第一个非 json 列兜底为主键(v0.7.3)', async () => {
|
||||
const legacyName = uniqueDB();
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
const request = indexedDB.open(legacyName, 1);
|
||||
request.onupgradeneeded = () => {
|
||||
request.result.createObjectStore('nokey_tbl', { autoIncrement: true });
|
||||
};
|
||||
request.onsuccess = () => {
|
||||
const db = request.result;
|
||||
const tx = db.transaction('nokey_tbl', 'readwrite');
|
||||
tx.objectStore('nokey_tbl').add({ code: 'c1', name: 'X' });
|
||||
tx.objectStore('nokey_tbl').add({ code: 'c2', name: 'Y' });
|
||||
tx.oncomplete = () => { db.close(); resolve(); };
|
||||
tx.onerror = () => reject(tx.error);
|
||||
};
|
||||
request.onerror = () => reject(request.error);
|
||||
});
|
||||
|
||||
const target = new MetonaSqlark({ name: uniqueDB(), mode: 'disk' });
|
||||
await target.init();
|
||||
// 此前无主键 → createSchema 抛 SCHEMA_ERROR 中断整个迁移;现在 code 列兜底为主键
|
||||
const result = await migrateFromIndexedDB({ dbName: legacyName, engine: 'disk', target });
|
||||
expect(result.migratedTables).toEqual(['nokey_tbl']);
|
||||
expect(result.rowCount).toBe(2);
|
||||
const rows = await target.table('nokey_tbl').select().execute();
|
||||
expect(rows).toHaveLength(2);
|
||||
await target.close();
|
||||
});
|
||||
|
||||
it('全 json 列的旧库:无可用主键 → 跳过该表不中断迁移(v0.7.3)', async () => {
|
||||
const legacyName = uniqueDB();
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
const request = indexedDB.open(legacyName, 1);
|
||||
request.onupgradeneeded = () => {
|
||||
request.result.createObjectStore('json_tbl', { autoIncrement: true });
|
||||
request.result.createObjectStore('ok_tbl', { keyPath: 'id' });
|
||||
};
|
||||
request.onsuccess = () => {
|
||||
const db = request.result;
|
||||
const tx = db.transaction(['json_tbl', 'ok_tbl'], 'readwrite');
|
||||
tx.objectStore('json_tbl').add({ payload: { a: 1 } });
|
||||
tx.objectStore('ok_tbl').add({ id: '1', name: 'Z' });
|
||||
tx.oncomplete = () => { db.close(); resolve(); };
|
||||
tx.onerror = () => reject(tx.error);
|
||||
};
|
||||
request.onerror = () => reject(request.error);
|
||||
});
|
||||
|
||||
const target = new MetonaSqlark({ name: uniqueDB(), mode: 'disk' });
|
||||
await target.init();
|
||||
const result = await migrateFromIndexedDB({ dbName: legacyName, engine: 'disk', target });
|
||||
// json_tbl 无可用主键被跳过;ok_tbl 正常迁移
|
||||
expect(result.skippedTables).toContain('json_tbl');
|
||||
expect(result.migratedTables).toEqual(['ok_tbl']);
|
||||
await target.close();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user