36 KiB
36 KiB
Changelog
All notable changes to MetonaSqlark will be documented in this file.
[0.4.2] - 2026-08-09
Fixed
- AriaEngine 残缺 SSTable 导致打开崩溃(P0) — 异常退出后下次打开抛原生
RangeError: offset is out of bounds,库打不开只能删库重建。三处根治:SSTableReader读路径防御:块偏移/大小越界时跳过该块(get/rangeScan/scanAll 返回空或继续),索引块/块内条目解析全程边界检查,不再抛 RangeError- 打开时完整性校验:
LSM.init()校验 meta 引用的文件存在、长度 ≥ 头、可解析,残缺的忽略并清理 meta/文件(自愈,不阻塞打开) - WAL 原子写入:
IndexedDBBackend新增writeMany/deleteMany(单事务批量写删),WAL 记录与 count 计数同事务提交,中断整体回滚不留半写
- IndexedDB 版本管理缺陷导致重启必报 VersionError(P0) — 建表每张版本号 +1 而
open()用config.version,重启后版本过低直接失败。open()遇 VersionError 自动用无版本参数探测库当前实际版本并以该版本重开 create({ version: 0 })抛原生 TypeError(P0) — 版本 < 1 统一归一化为 1,不再直接炸indexedDB.open(name, 0)- WAL 写丢失(P1) — 连续快速写入 200 条 close+重开实测丢 4 条。WAL 恢复不再依赖 count 计数,改为扫描全部
__wal_*键(数值排序拼接),count 键只作序号分配器;配合原子写入彻底消除 count/记录竞态 - AriaEngine.close() 不 checkpoint,WAL 无限重放(P1) — close 前补
wal.checkpoint()截断,下次打开不再重放已落盘的历史记录 - 引擎内部错误不包装 DatabaseError(P1) — AriaEngine
open()整体 try/catch 包装为ARIA_OPEN_ERROR;IndexedDBEngine 打开路径统一IDB_OPEN_ERROR/IDB_VERSION_ERROR/IDB_BLOCKED,应用层可拿 code 分类处理 migrateTo版本门槛与引擎版本脱节(P2) — 迁移版本持久化到库内(IStorageEngine.getMeta/setMeta可选接口,Aria 存 backend、IndexedDB 复用__metona_schemastore、OPFS 存元数据文件、Hybrid 委托磁盘引擎),重启后从持久化版本继续执行,不重跑不跳跑- IndexedDB
onblocked直接 reject(P2) — 改为等待后重试(阻塞解除后 success 仍触发,仅超时判失败,并防止连接泄漏),多次重试仍阻塞才抛IDB_BLOCKED - 缺少官方崩溃恢复/自愈接口(P2) — 新增
db.repair()(校验清理损坏数据并恢复一致性)与db.clearAll()(清空全部数据与表结构,保留库),全部引擎(Aria/IndexedDB/OPFS/Memory/Hybrid)实现,无需删库重建 - IndexedDB
__metona_schemastore 缺失时元数据无法落盘 —open()时确保 schema/meta store 存在(缺失则一次版本升级创建)
Fixed(深度审计第二轮)
- AriaEngine 二级索引跨重启丢失(严重) — 重开只恢复 schema 不恢复索引 LSM:索引查询静默回退全表、
createIndex因 schema 标记已存在而直接 return → 索引永久缺失;且 WAL 崩溃恢复只回放主 LSM,最后一批写入的索引缺失 → 索引查询丢行。三处根治:open 时按 schema 标记重建索引 LSM(数据已持久化直接加载)、close 时同步落盘全部索引 LSM、WAL 恢复完成后全量重建索引 - AriaEngine Compaction 依赖缓存丢数据(严重) —
compactLevelAsync仅从 LRU 缓存读 SSTable,缓存未命中(单文件超缓存上限被驱逐、频繁 flush)时跳过全部文件并从 levels 移除 → 运行中数据全部不可见(重启才恢复)。改为从存储兜底加载;无有效数据时将文件放回 levels 不删除 - AriaEngine flush/compaction 失败卡死写路径(严重) — flushChain 链上任务抛错后永久 rejected,后续所有 flush/compaction 挂起。链上任务统一吞错恢复(记录告警,链继续)
- ALTER TABLE 在 IndexedDB/Hybrid/OPFS 引擎不持久化 — v0.4.1 只给 Aria 加了引擎级
alterTable,其余引擎走通用路径只改内存 schema 引用:重启后 ADD/DROP 全部回退,DROP 的行数据也残留。为 IndexedDB(持久化 schema + 重写存储行)/ Hybrid(双引擎)/ OPFS / Memory 统一实现引擎级alterTable - IndexedDB 事务内 DDL 崩溃(严重) — 事务内建表 commit 时 IDB 无对应 store 报错;事务内删表 IDB store 残留 → 重启幽灵表。
flushToIDB提交时 diff 内存表与 IDB store:缺失的创建(含 schema 持久化)、多余的删除(含 schema 记录清理);commit 顺序调整为"先刷盘后提交内存快照",失败可回滚 - Hybrid 内存/磁盘引擎共享 schema 引用污染 —
reloadMemoryFromDisk把磁盘引擎的 schema 对象直接存入内存引擎,任一引擎 ALTER 都改到对方。MemoryEngine.createTable深拷贝 schema(全引擎受益) - Hybrid commit 失败路径错误掩盖 — 磁盘已提交后内存提交失败时调
diskEngine.rollbackTransaction()抛 TX_NONE 掩盖原错误;如实上报磁盘已提交状态 - AriaEngine.close 运行期状态残留 — close 后 MVCC/事务快照/savepoint 残留,重开后
beginTransaction报 TX_ACTIVE。close 统一清理 - VACUUM 对 2-3 个文件层级不压缩 —
compactLevelpublic 门槛与内部自动调度门槛混用(内部 4 / VACUUM 期望 2)。分离参数化
Fixed(生产就绪审计第三轮)
- Aria 事务进行中 checkpoint 截断 WAL(严重,P0) — checkpoint(tick/forceCheckpoint)在活跃事务中途执行时 truncate WAL,BEGIN/INSERT 记录被截断,事务 COMMIT 后崩溃恢复丢失整个事务数据。CheckpointManager 包装 WAL:事务活跃时跳过截断(close/repair/clearAll 仍正常截断)
- Aria dropTable / DROP_TABLE 恢复不清理二级索引(P1) — 索引 LSM 孤儿残留,重建同名表后旧索引数据污染新表(按旧值索引查询返回不匹配行)。新增
cleanupTableIndexes:dropTable、崩溃恢复、ALTER DROP 索引列统一清理 - Aria ALTER TABLE DROP 索引列残留(P1) — 删列但索引 LSM 保留,后续同名列索引数据脏
- Aria freezeMemtable 阈值逐次衰减(P2) — 新 memtable 用旧表已用大小当阈值,手动 flush 后阈值塌缩 → 频繁小文件。改回配置阈值
- Aria 事务中 DDL 静默不一致(P2) — 事务快照只覆盖行数据,createTable/dropTable/alterTable 无法回滚;与 Memory/IndexedDB 可回滚行为不一致 → 显式抛
NOT_SUPPORTED(不再静默) - ON UPDATE 外键级联未实现(P2,声称支持但静默忽略) — 实现
ON UPDATE CASCADE/SET NULL/RESTRICT(Memory + Aria 双引擎):更新主键时级联更新/拒绝,含二级索引与 WAL 记录,先全量 RESTRICT 检查再执行防部分修改;update 同时支持主键变更(旧键删除 + 新键落表) - MVCC commit/rollback 全库版本遍历(P2 性能) — 大表事务 commit O(全库版本数)。按事务记录写入的 key 精准清理(O(写入数))
- OPFS 空表重启消失 + schema/索引丢失(P1) — 表 schema 持久化到元数据文件:createTable/dropTable/alterTable/createIndex 同步;重启从 schema 恢复(空表保留、主键/索引标记/约束完整),无 schema 的旧库回退数据推断(兼容)
- OPFS dropTable 不清理 schema 记录(P1) — 重启恢复幽灵表;删表同步清理
- OPFS 并发写验证 — 审计确认内存写同步、持久化快照总是最新(单标签页无丢更新竞态),新增并发写回归测试锁定行为
- VACUUM 返回值语义 —
gcVersions返回活跃事务数改为全局提交序列号
Changed
- 测试 894 → 944(50 套件),新增
tests/v042-fixes.test.ts(23 条问题清单回归)、tests/v042-hardening.test.ts(12 条深度审计回归)与tests/v043-hardening.test.ts(15 条生产就绪回归:事务×checkpoint、DDL 索引清理、OPFS 持久化、memtable 阈值、红黑树 5000 次随机压力、onUpdate 级联) - 版本号升至 v0.4.2
[0.4.1] - 2026-08-08
Added
- AriaEngine 外键级联删除 — 对齐 Memory 引擎:
CASCADE(递归多层)、SET NULL、RESTRICT(抛FOREIGN_KEY_VIOLATION),含二级索引清理、WAL 记录、事务内可提交/回滚、环路保护 AriaEngine.clearAll()— 重置数据库(清空后端存储/LSM/WAL/MVCC/二级索引),实例可继续使用;供演示页刷新场景与 API 用户使用- 演示页引擎切换器 — 右上角
⚡ Memory/🌲 Aria一键切换,Aria 模式每次加载clearAll()保证演示确定性;aria 预设文案更新(数据库即 Aria)
Changed
- 版本号升至 v0.4.1
- 测试 880 → 894(46 → 47 套件)
AriaEngine级联行为与 MemoryEngine 对齐:SET NULL不影响删除返回行数
Fixed
- JOIN 主表 WHERE 不下推 —
SELECT ... FROM orders o JOIN users u ... WHERE o.user_id = '1'的 WHERE 只在 JOIN 后过滤,二级索引形同虚设。v0.4.1 将主表前缀等值条件下推到引擎(extractPushableWhere),索引真正生效 - DROP INDEX 不存在的索引静默成功 — Memory/Aria 引擎
dropIndex对无索引列静默返回,改为抛INDEX_NOT_FOUND - Memory 索引查找不支持
$eq对象形式 — SQL 解析器生成的{ $eq: value }等值条件不走哈希索引(仅简单值走),补$eq分支 - 演示页预设数据被前序预设污染 — 连续点击预设时,cascade(删除 Alice/重建 orders)、truncate、alter 等会修改种子数据,后续预设(如 index)查询返回空。
loadPreset点击预设前自动重置数据库到初始状态,每个预设可预期演示 - Aria ALTER TABLE 不生效(严重) —
DROP COLUMN仅改 schema 引用,find()返回行副本无法就地删除,存储行残留已删列值(SELECT * 仍显示);且 ALTER 不持久化 schema,重启后列定义回退。新增引擎级alterTable(IStorageEngine可选接口):Aria 重写主 LSM 移除列值 +persistSchemas+ WAL UPDATE 记录,崩溃恢复后 schema 与行一致 - 裸布尔列条件不支持(严重) —
WHERE done/CASE WHEN done THEN解析失败(无比较运算符即抛错),条件被忽略导致 CASE 恒走 ELSE。parser 支持裸列真值判断({ col: { $eq: true } }) - Aria $in 返回重复行 — IN 子查询含重复值(如 Alice 两条订单)时 PK/二级索引
$in逐值查找重复 push,按主键去重
[0.4.0] - 2026-08-08
Added
- 流式查询 API —
db.queryStream(sql, onRow)/db.table(name).stream(onRow)/IStorageEngine.findStream():- Aria 引擎走 LSM
rangeScanLazy惰性扫描,逐行回调不物化结果数组(大表友好) - Memory/Hybrid/OPFS 逐行迭代;IndexedDB 批量读入后逐行回调(保持接口一致)
- 支持 WHERE/LIMIT/OFFSET/列投影;JOIN/GROUP BY/UNION/聚合/ORDER BY 自动回退物化
- 用户 async 回调自动回退物化(同步扫描无法 await,避免吞 Promise)
- Aria 引擎走 LSM
- 多列 ON 哈希连接 — 复合等值条件(
ON a.tenant = b.tenant AND a.key = b.key)走哈希连接(含顶层$and展开),任一右列为索引/主键即可;不适用自动回退嵌套循环 - FROM 子查询(派生表) —
SELECT ... FROM (SELECT ...) AS alias WHERE ...,子查询结果作为行源,支持 WHERE/ORDER BY/LIMIT 与 JOIN 组合 - COUNT(DISTINCT col) — 聚合去重(COUNT/SUM/AVG/MIN/MAX 均支持),任意类型去重
- NULLS FIRST / NULLS LAST —
ORDER BY col ASC NULLS FIRST等,NULL 位置固定不受升降序反转 - 普通列别名 —
SELECT name AS n/SELECT name n(此前仅聚合/CASE 支持别名),别名可用于 ORDER BY - 无表查询与字符串常量列 —
SELECT 1/SELECT 'lit' AS x(无需 FROM),''转义与常量列投影
Fixed
- AriaEngine 崩溃恢复后已删除表/数据复活(严重,P0) — WAL 回放忽略
DROP_TABLE而CREATE_TABLE无条件恢复 schema,删表后崩溃重启表+数据全部复活。v0.4.0 新增applyDropTableRecovery()回放删除 schema + 清除 LSM 残留 - WAL 恢复后不截断 — 每次重启重复回放 + WAL 无限膨胀。恢复完成将回放数据落盘后
wal.checkpoint()截断 - MemoryEngine update 不维护索引(P0) —
update()后唯一约束可被绕过、按新值索引查询丢行。removeIndexEntries()在 update/delete/级联删除/SET NULL 前清理旧值索引 - Aria 事务内读不到自己写入的行 —
update/delete/count/clear的getAllRows()不合并txnSnapshot,事务内先 insert 再 update/delete 失效;统一mergeTxnSnapshot() - Aria TRUNCATE 不写 WAL —
clear()崩溃恢复后丢失;事务内清空走快照删除标记,提交生效 - WAL 大小阈值在 full 模式永不触发 —
getBufferedBytes()跟踪真实字节数替代缓冲计数估算 - rollback 后二级索引残留 — 事务内直接写入索引 LSM,回滚后对受影响表全量重建索引
- Savepoint 回滚 MVCC 不一致 —
discardVersions()清理版本链保留事务登记 - PK 范围查询字符串算术 bug —
$gt/$gte/$lt/$lte用Number(v)+1构造 key 对字符串 PK 失效;改为主 LSM 前缀扫描 + 条件过滤;主键列不再建冗余二级索引(PK$in走多次精确查找) - SQL 字符串
''标准转义 — 双引号转义此前从未生效(lexer 条件先于转义分支退出);重写readString - INSERT INTO ... SELECT 位置错位(严重) — 源行
validateRow跳过 undefined 值导致行键缺失/乱序(如 ALTER 加列后省略列插入的行),Object.values位置映射把 age 数字填进 email 列报类型错。改为按源表 schema 列顺序/SELECT 列列表对齐,缺列不填 - ORDER BY / GROUP BY 表前缀列 —
ORDER BY o.amount/GROUP BY u.name解析失败(Expected ';' ... got "."),parser 支持table.column引用,executor 非 JOIN 路径剥离前缀 - 关联 EXISTS 绑定失效(严重) —
SELECT u.name ... WHERE EXISTS (SELECT 1 FROM o WHERE o.user_id = u.id)返回空:引擎按 SELECT 列投影后外层行缺id键,$col绑定为 null。关联子查询路径强制plan.columns=['*']取完整行;非 JOIN 路径 SELECT 列带表前缀(u.name)统一剥离 - HAVING 标量子查询失效(静默返回空) —
HAVING SUM(o.amount) > (SELECT AVG(amount) FROM orders)的$subquery未解析 + 聚合表达式键(SUM(o.amount))与别名键(spent)不匹配。HAVING 先resolveSubqueries,GROUP BY 结果维护「表达式键→别名键」映射做归一化
Changed
- 版本号升至 v0.4.0
- 测试 837 → 876(44 → 46 套件),覆盖率 81.1% → 81.5%(Lines 84.7%)
[0.3.2] - 2026-08-08
Added
- CASE WHEN 用于 WHERE —
WHERE CASE WHEN cond THEN a ELSE b END = 'x'逐行求值(含 NOT/AND/OR 组合) - CASE WHEN 用于聚合 —
SUM(CASE WHEN age > 18 THEN 1 ELSE 0 END)、COUNT/AVG/MIN/MAX(CASE...)、GROUP BY + CASE非聚合列 - JOIN 哈希连接 — 等值 ON + 右表主键/索引列时,收集左表连接值 → 一次
$in查询 → 哈希映射匹配,替代嵌套循环(INNER/LEFT JOIN,O(N+M));不适用自动回退 - 多标签页同步 —
multiTabSync: true配置 + BroadcastChannel:- SQL 写语句(INSERT/UPDATE/DELETE/DDL)自动广播表变更
- Table API 写入(insert/insertMany/update/delete/clear/drop)自动广播
- 其他标签页收到
external变更事件(订阅者可见)+ Hybrid 内存自动重载 db.broadcastChange(table)手动广播
- IndexedDB schema 持久化 —
__metona_schemastore 保存完整列定义,reopen(页面刷新/重连)后恢复;旧数据回退为"主键 + 索引 + 样例推断"
Fixed
- IndexedDB reopen 后 schema 丢失(严重) — schema 仅存内存缓存,close 后重开连接表结构即丢失(INSERT 列映射截断、UPDATE 全列失效)。v0.3.2 持久化 + 重建
- where-matcher 顶层 $not 不生效 —
NOT (expr)解析为顶层{ $not }但被当作字段匹配,始终返回 true - CASE 剥离后空
$not恒假 — 引擎层执行NOT(true)过滤掉所有行
Changed
- 版本号升至 v0.3.2
[0.3.1] - 2026-08-08
Added
- CASE WHEN 表达式(SELECT 列) —
CASE WHEN cond THEN value [WHEN ...] [ELSE value] END [AS alias]- 多 WHEN 按顺序匹配、ELSE 缺省返回 null
- THEN/ELSE 值支持字面量(字符串/数字/布尔/null)与列引用
- 条件支持 AND/OR/比较运算符/IS NULL 等完整 WHERE 语法
- 引擎层返回原始行供求值(避免投影丢失条件列),与普通列混合投影
- JOIN + 关联子查询 — JOIN 结果的 WHERE 支持
EXISTS (SELECT ... WHERE o2.x = u.y)与$col引用外层行,逐行绑定求值 - WAL 批量组提交 —
WAL.appendBatch()合并多条记录为一次底层写入;引擎 insert/update/delete 批量记录后一次落盘(写放大从 O(N) 降为 O(1)) parseWhereCondition()导出 — 独立条件表达式解析(CASE WHEN 求值内部使用)
Fixed
- LSM pending frozen 可见性 — 异步 flush 链期间,中间冻结的 MemTable 仅存在于闭包中,读取路径不可见导致数据缺失。新增
frozenMemtables列表,get/rangeScan/getAllEntries 遍历所有 pending frozen(新→旧) - flush 缓存裁剪与预加载竞争 — flush 完成时的 LRU 裁剪会驱逐 prefetch 刚加载的 SSTable,导致扫描静默丢数据。prefetchRange/prefetchKeys 先等待 flush 链完成再加载
- CASE 值解析顺序 —
true/false/null字面量被误判为列引用
Changed
- 版本号升至 v0.3.1
[0.3.0] - 2026-08-08
Added
- SQL 多语句支持 —
parseAll()解析分号分隔的多条语句,db.query()顺序执行并返回最后一条结果(parse()保持单语句兼容) - 事务语句(TCL) —
BEGIN/COMMIT/ROLLBACK(支持可选 TRANSACTION 关键字),直接驱动引擎层事务,五引擎可用 - INSERT INTO ... SELECT — 支持
INSERT INTO t (cols) SELECT ...(含 WHERE 过滤、列映射) - UNION / UNION ALL — 支持去重合并与链式组合(
A UNION B UNION C),右侧结果按位置投影到左侧列结构 - CREATE INDEX / DROP INDEX — 动态二级索引:
CREATE [UNIQUE] INDEX idx ON table (col)/DROP INDEX idx ON table (col)- 五引擎实现:Memory 哈希索引 / IndexedDB 版本升级建
idx_col/ OPFS 委托 / Hybrid 双写 / Aria 动态 LSM 索引 - Aria 主键索引受保护(不可 DROP);CREATE INDEX 对已有数据立即建索引(回填),后续写入自动同步
- EXISTS / NOT EXISTS — 支持关联子查询(
WHERE EXISTS (SELECT 1 FROM o WHERE o.user_id = u.id)),逐行绑定外层上下文求值 - 别名 WHERE 修复 —
WHERE u.age > 20(主表别名前缀)此前不工作,v0.3.0 字段名规范化(JOIN 路径不受影响) SELECT 1常量列 — 数字字面量可作为 SELECT 列(EXISTS 子查询常见用法)- benchmark 页面 —
site/benchmark.html浏览器内实测 Memory / Aria 引擎 × 1K/10K/50K 行的 INSERT/PK 查询/索引查询/UPDATE/DELETE 吞吐(ops/sec) parseAll/ 新 AST 类型导出 —SelectUnionStatement/CreateIndexStatement/DropIndexStatement/BeginTransactionStatement等
Changed
- 版本号升至 v0.3.0
Fixed
NOT EXISTS解析丢 EXISTS token 导致 parse 失败
[0.2.6] - 2026-08-08
Fixed
- AriaEngine 二级索引 SSTable 互相覆盖(严重) — 主 LSM 与二级索引 LSM 此前共享同一
sstableStore(id 空间 + meta 列表),allocateId()返回Date.now()且各 LSM 从同一 meta 恢复nextSSTableId,高频写入时 id 冲突导致索引数据文件覆盖主数据、meta 与数据错配。v0.2.6 按命名空间隔离(文件前缀 + meta key + 独立 id 序列),索引 LSM 各持独立 store - LSM 多版本读取顺序错误(严重) —
levels[]数组按push追加(新文件在尾部),但get()/rangeScan从头遍历(旧文件优先),同一 key 跨多次 flush 更新后读到旧值;MergeIterator去重只取"先出堆者",不保证最新来源。v0.2.6 改为"数组头部即最新"(unshift+ 按 id 降序加载),MergeIterator 显式取 sourceIndex 最小者 - LZ4 往返不一致 — ① 匹配长度超过 19 字节被截断但
si跳过全部匹配,解压丢数据;② matchField=0 的组合 token 与纯字面量 token 格式歧义;③ 字面量累积超过 15 字节后组合 token 永远无法输出;④ 输出缓冲区maxOut不足导致越界写入;⑤ 压缩失败时返回原样 input,解压端无法区分。v0.2.6 重写压缩器(长匹配分段、纯字面量 token 语义明确、动态上限) - React/Vue 集成运行时 ReferenceError —
useDatabase/useSqlarkDatabase用import type导入MetonaSqlark但运行时new MetonaSqlark(),@ts-nocheck掩盖此 bug,实际使用必炸。改为 value import - sstableCache 无限增长 — SSTable 缓存无内存上限且
init()预加载全部数据,大库 OOM。v0.2.6 引入 LRU 容量上限(bufferPoolPages×pageSize),查询前异步预加载兜底(修复缓存未命中静默返回 null 丢数据的隐患) - integrations 子路径缺失 — README 宣称
metona-sqlark/react、metona-sqlark/vue可用但exports未声明,现已补齐(react/vue 为 peer dependency,rollup external)
Changed
- Buffer Pool 配置真正生效 —
bufferPoolPages从无效配置变为 SSTable 缓存容量上限(默认 256 页 ≈ 1MB 可控内存) - LZ4 格式变更 — 旧版本压缩数据与新解压器不兼容,使用
compression: true的用户需重新导入数据 - SSTable 持久化串行化 — flush/compaction 改为串行链(
flushChain),id 分配与持久化顺序一致,消除 fire-and-forget 竞态 - 文档数据修正 — 测试 761(41 套件)、覆盖率 81.1%(此前 91.0% 为排除 Aria 模块的陈旧数据)、体积 ~105KB / gzip ~27KB
Added
- AriaEngine 缓存内存上限测试 — 9 个测试:LRU 上限约束、驱逐后全表/PK/索引查询完整性、UPDATE/DELETE 全量作用、写路径上限、命名空间隔离回归、多版本回归、tombstone 回归
- LZ4 往返一致性测试 — 6 个往返测试(重复/文本/随机/边界长度/15 字节边界/长匹配)
- CryptoManager 加解密测试 — 7 个测试(往返/错误密码/不同 salt/实例隔离/全局兼容层/4KB 页面)
- React/Vue hooks 集成测试 — 16 个测试(jest.mock 零依赖:mount 执行、错误路径、refresh、注入防护、数据库初始化)
- jest.setup.js WebCrypto polyfill — jsdom 环境补齐
crypto.subtle支持 AES-GCM
[0.2.5] - 2026-07-29
Fixed
- 版本号统一 —
constants.tsVERSION 从'0.2.0'更新为'0.2.5',修正index.ts/utils.ts/CONTRIBUTING.md中过时的版本注释和数据 - AriaEngine OPFS 后端映射 —
core.ts中mode: 'aria'+diskEngine: 'opfs'时实际使用 Memory 后端的 bug 已修复 _onError接入执行路径 —query()/defineTable()/dropTable()/transaction()/importTable()的 catch 路径现在调用_onError全局错误回调maxRowsPerQuery生效 —QueryExecutor构造时接收maxRowsPerQuery参数,SELECT 结果在返回前截断- WAL full 模式真正同步 —
WAL.append()改为async,full模式下await this.store.append()真正等待写入完成,不再 fire-and-forget - PluginManager.install 传 db 实例 —
register()增加可选db参数,core.ts初始化时传入this,插件可获取 db 引用
Changed
- SSTableReader 二分查找统一 —
locateBlockGE/locateBlockLE从线性扫描改为二分查找,rangeScan 性能在大型 SSTable 下不再退化 - crypto 实例化 — 全局状态改为
CryptoManager类,每个 AriaEngine 实例可拥有独立加密配置,保留全局函数向后兼容 - compactLevelSync 接口公开化 — LSM 新增 public
compactLevel()方法,vacuum()不再使用as any绕过 private 访问 - WAL 大小阈值接入 checkpoint —
CheckpointManager接收walSizeThreshold参数,WAL 缓冲超阈值时自动触发 checkpoint
Added
- ALTER TABLE 语法 — 支持
ALTER TABLE ... ADD COLUMN/DROP COLUMN(含可选 COLUMN 关键字) - TRUNCATE TABLE 语法 — 支持
TRUNCATE TABLE name快速清空表数据 - MVCC 接入读写路径 — 事务内 insert/update/delete 调用
mvcc.writeVersion/mvcc.deleteVersion,版本链作为 undo log - IndexedDB 索引利用 —
IndexedDBEngine.find等值查询时优先使用 IDB 索引(idx_col命名约定),避免全量 getAll - SQL 注入防护 — React
useTable/ VueuseSqlarkTable增加表名合法性校验(/^[a-zA-Z_][a-zA-Z0-9_]*$/)
[0.2.4] - 2026-07-27
Added
- 二级索引 — 每列可独立维护 LSM Tree 索引,
$eq/$in/$gt/$lt走索引 O(log n) - MVCC 接入引擎 — MVCCManager 正式投产,替换 ad-hoc txnSnapshot
- MVCC 自动 GC — 每 10 次 checkpoint 自动回收过旧版本(保留最新 100 个)
- Bloom Filter 序列化 — 写入 SSTable footer + 读取时加载 + 查询时 probe 快速否定
- WAL 大小阈值 —
walSizeThreshold配置(默认 16MB),超阈值强制 checkpoint - 内存预算 —
maxMemoryMB配置(默认 64MB)
Changed
- WAL 默认同步模式 —
walSyncMode从'batch'改为'full',消除 crash 丢数据风险 - 查询优化 —
tryIndexLookup扩展支持非 PK 列索引查找
[0.2.3] - 2026-07-27
Fixed
- RB-Tree fixDelete 完整实现 — 补全标准红黑树删除修复,保证 O(log n)
- LSM SSTable 缓存预热 —
init()预加载所有 SSTable,消除 cache miss - OPFS 数据恢复 —
open()自动从 OPFS 文件加载已有表数据到内存 - Aria WAL 事务恢复 — 两阶段恢复:仅回放已提交事务,未提交数据不回放
- LZ4 格式修复 — 重写 token 格式,消除中间字面量 token 歧义
[0.2.2] - 2026-07-27
Added
- OPFS 自研存储后端 — AriaEngine 新增
OPFSBackend,纯浏览器文件系统 API,零 IndexedDB 依赖- 每个 key 对应一个二进制文件,存储在
navigator.storage.getDirectory()下 - 支持 read/write/delete/list/exists/clear 完整接口
- 页面文件(4KB)、WAL 日志、Schema、SSTable 全部存储为独立文件
{ dbName }/pg_1,{ dbName }/__wal_0,{ dbName }/__aria_schemas...
- 每个 key 对应一个二进制文件,存储在
Changed
AriaEngineConfig.storageBackend已支持'opfs',AriaEngine.open()自动选择 OPFSBackend
[0.2.1] - 2026-07-27
Fixed
- WAL CRC 校验验证 — 恢复时计算并验证 CRC32,损坏记录自动跳过并告警
- Hybrid 引擎提交顺序 — commit 先写磁盘再写内存,磁盘失败回滚内存,消除数据不一致风险
- RESTRICT 外键行为修正 — 检测到引用行时抛出
FOREIGN_KEY_VIOLATION,不再静默保留孤儿 - SSTable rangeScan 边界保护 — 空索引或 startBlockIdx > endBlockIdx 时安全返回
Added
- ColumnDef 约束激活 —
maxLength/min/max约束在checkFieldType中正式生效 - 查询结果上限 —
DatabaseConfig.maxRowsPerQuery(默认 0 不限制),防止超大结果集 OOM - onError 全局回调 — 配置中的
onError回调实际接入 CRUD 异常路径 - debug 调试模式 —
DatabaseConfig.debug: true输出[MetonaSqlark:name]前缀的结构化日志 - 浏览器兼容性声明 — README 增加 Chrome 80+/Firefox 80+/Safari 14+/Edge 80+ 支持矩阵
Changed
- MemoryEngine RESTRICT 外键行为:从"不级联保留孤儿"改为"禁止删除抛异常"
- Hybrid 引擎 commitTransaction 磁盘优先于内存
- DB_DEFAULTS 新增
maxRowsPerQuery: 0和debug: false
[0.2.0] - 2026-07-27
Added
- AriaEngine 自研存储引擎 — 基于 LSM-Tree 的页面式存储引擎,19 个新模块,~3500 行 TypeScript
- 页面格式层 (
page/): 4KB Slotted Page 编解码、Tuple 二进制序列化、CRC32 校验 - Buffer Pool (
buffer/): LRU 页面缓存 + 驱逐策略,可控内存占用 - LSM-Tree 索引 (
index/): MemTable (红黑树) + 多级 SSTable + Leveled Compaction - Bloom Filter (
index/bloom.ts): FNV-1a + Murmur 双哈希,快速键否定判定 - SSTable 构建器/读取器 (
index/sstable_builder.ts,sstable.ts): 二分查找 + 范围扫描 - Merge Iterator (
index/merge_iterator.ts): 最小堆多路归并,去重保留最新值 - WAL (
wal/): 二进制日志格式 (LSN/type/txnId/table/key/json/CRC) + Checkpoint 管理 - MVCC (
transaction/mvcc.ts): 版本链 + 快照隔离 + GC - 存储后端 (
store/): IndexedDB / Memory 双后端抽象 - LZ4 压缩 (
compression/lz4.ts): 简易页面级压缩
- 页面格式层 (
mode: 'aria'— 新增存储模式,可通过MetonaSqlark.create({ mode: 'aria' })激活- Schema 持久化 — 表结构自动保存到
__aria_schemas,重启自动恢复 - SSTable 元数据管理 — SSTable 索引信息持久化,启动时自动扫描加载
- 事务感知 CRUD — insert/update/delete 在事务中缓冲到 snapshot,commit 批量写入 LSM
- 244 个 AriaEngine 专项测试 — 覆盖生命周期/表管理/CRUD/事务/持久化/SQL 集成/页面格式/LSM/压缩
Changed
StorageMode类型新增'aria'STORAGE_MODES数组新增'aria'createEngine()支持mode: 'aria'分支- 测试从 318 → 526,套件从 20 → 27
- 新增 7 个模块级测试文件:
aria-page、aria-index、aria-sstable、aria-buffer、aria-wal-mvcc、aria-compress、aria - LRUList 修复 size 追踪 bug
- WAL 存储改为按记录独立 key(避免拼接缓冲区越界)
- CheckpointManager 解耦 BufferPool 依赖
Fixed
- LZ4 压缩无限循环 — 字面量分支在发现匹配后回退导致 litLen=0 死循环,CI 卡死根因
- SSTableReader.get() 自比较 bug — 参数 key 被循环变量遮蔽导致永远返回第一条
- CheckpointManager 测试 null 引用 — 改为 Mock 对象避免 TypeError 导致进程无法退出
- IndexedDB 持久化测试 — 替换为 Memory Backend 验证,消除 fake-indexeddb timer 堆积
- LSM.flush() 不必要 setTimeout — 替换为 Promise.resolve(),消除额外 timer 延迟
[0.1.14] - 2026-07-26
Fixed
- IndexedDB 事务原子性:
flushToIDB改为单 IDB 事务包裹 clear+insert,消除崩溃丢数据风险 - 多标签页冲突:
open()添加onversionchange监听,其他标签页升级版本时自动关闭过期连接 - Memory 引擎幂等:
open()重复调用安全无副作用 - 关闭时清理
onversionchange监听器,防止内存泄漏
[0.1.13] - 2026-07-26
Added
- 事务回滚机制:
IStorageEngine新增beginTransaction/commitTransaction/rollbackTransaction接口- MemoryEngine: 快照式回滚(深拷贝 tables/schemas/indexes)
- IndexedDBEngine: 延迟写入策略(事务中仅写内存,commit 批量刷 IDB)
- OPFSEngine: 快照式回滚(commit 批量写文件)
- HybridEngine: 同时代理内存+磁盘引擎事务
- 子查询支持: SQL Parser + Executor 支持
IN (SELECT ...)和op (SELECT ...)子查询- AST 新增
SubqueryExpression类型 - Parser 在 IN 和比较运算符后检测子查询
- Executor 新增
resolveSubqueries()递归解析,自动执行子查询并替换为具体值
- AST 新增
- 外键级联操作: ColumnDef 新增
onDelete/onUpdate选项- 支持
CASCADE(递归级联删除)、SET NULL、RESTRICT - SQL Parser 解析
REFERENCES table(col) ON DELETE CASCADE ON UPDATE CASCADE - MemoryEngine 内置
cascadeDelete()递归级联逻辑
- 支持
- 连接池管理:
MetonaSqlark.connect()静态方法- 同名数据库复用已打开实例,引用计数管理
db.disconnect()释放连接,归零自动 closeMetonaSqlark.disconnectAll()强制关闭所有连接
Changed
TransactionManager.execute()调用引擎层 begin/commit/rollback 实现真正原子性- IndexedDBEngine CRUD 事务感知:活跃事务中延迟 IDB 写入
- ASTColumnDef / astColumnToColumnDef 支持 references/onDelete/onUpdate 透传
Fixed
- IndexedDBEngine 事务中 find/count 从内存缓存读取(保证读到未提交变更)
- SQL Parser parseColumnDef 循环条件扩展,避免 REFERENCES 语法解析中断
[0.1.12] - 2026-07-26
Added
MeSqlark别名导出,与MetonaSqlark完全等价metona-sqlark.cjs.jsCommonJS 构建产物- 完善的
where-matcher.ts消除 220+ 行重复代码 $col列引用支持 JOIN ON 条件$and/$or嵌套支持(字段级 + 顶层)$not逻辑非操作符$like正则缓存加速projectColumns列投影支持table.column格式DISTINCT去重支持(O(n) 时间,列值拼接优化)- 测试覆盖率提升至 93.46%(264 测试/15 套件)
Changed
where-matcher统一 MemoryEngine / IndexedDBEngine / Executor 的 WHERE 逻辑- JOIN ON 匹配支持
$col语法 - LIKE 正则改为缓存式编译
- Executor DISTINCT 用列值拼接代替 JSON.stringify
- JOIN 嵌套循环连接优化:避免 ON 时对象扩散
Fixed
- IndexedDBEngine
update/delete方法正确同步内存缓存 - OPFSEngine
getTableNames兼容entries()返回值 - SQL Parser 正确处理字符串转义字符
- SQL Parser 正确处理表别名(无 AS 关键字)
- SQL Parser 解析
IS NULL/IS NOT NULL/NOT LIKE peekTokenIs方法正确暴露给语法分析- 多处边界条件空值/假值处理
[0.1.11] - 2026-07-25
Added
- React 集成 hooks:
useQuery,useTable,useDatabase - Vue 集成 composables:
useSqlarkQuery,useSqlarkTable,useSqlarkDatabase - 发布订阅系统:
subscribe(),emit() - 数据迁移系统:
addMigration(),migrateTo() - 导入导出:
exportTable(),exportAll(),importTable() - 完整 SQL 解析器:
Lexer+Parser(递归下降) - SQL 支持: SELECT, INSERT, UPDATE, DELETE, CREATE TABLE, DROP TABLE
- JOIN 支持: INNER, LEFT, RIGHT, CROSS
- GROUP BY + HAVING + 聚合函数 (COUNT, SUM, AVG, MIN, MAX)
- DISTINCT, ORDER BY, LIMIT, OFFSET
- WHERE 条件: AND, OR, NOT, IN, LIKE, IS NULL
- Query Builder 链式 API:
select().where().orderBy().limit().execute() - 插件系统: 14 种生命周期钩子 + PluginManager
- Metadata 系统: ColumnDef 完整约束 (type/primaryKey/required/unique/index/default/references/maxLength/min/max)
Changed
- 架构重构为分层设计:Engine → QueryExecutor → Table/QueryBuilder → SQL Parser → Public API
- AST 作为统一中间表示,SQL 和 QueryBuilder 行为完全一致
- 测试框架完善:core / edge / groupby / join / query-system / sql / table / engine / transaction / plugin / hybrid 全覆盖
[0.0.1] - 2026-07-24
Added
- 初始项目骨架
- TypeScript 配置(严格模式)
- Rollup 构建(UMD / ESM / CJS / min / .d.ts)
- Jest + jsdom 测试环境
- ESLint + @typescript-eslint
- Gitea Actions CI 工作流
- 示例站点(index / demo / docs)
- 构建脚本 build.sh