Files
MetonaSqlark/CHANGELOG.md
T
thzxx d544501e1c
CI / test (18.x) (push) Failing after 5m11s
CI / test (20.x) (push) Failing after 5m8s
CI / test (22.x) (push) Successful in 9m58s
CI / test (24.x) (push) Successful in 9m56s
release: v0.3.2 — 质量加固 + SQL扩展 + 表达式 + 并发同步
v0.2.6 质量加固:
- 修复 AriaEngine 二级索引 SSTable 互相覆盖(命名空间隔离)
- 修复 LSM 多版本读取顺序错误 + MergeIterator 取最新来源
- 重写 LZ4 压缩器(往返一致性 + 缓冲区溢出)
- sstableCache LRU 上限 + 预加载兜底(BufferPool 配置生效)
- 修复 React/Vue 集成 import type 运行时 bug + exports 子路径
- 新增 38 个测试(LZ4往返/Crypto/集成), 删除伪测试

v0.3.0 SQL 功能扩展:
- 多语句 parseAll + 事务语句 BEGIN/COMMIT/ROLLBACK
- INSERT INTO ... SELECT + UNION/UNION ALL + EXISTS 关联子查询
- CREATE/DROP INDEX 五引擎实现 + 别名 WHERE 修复
- benchmark 页面 + 36 个新测试

v0.3.1 表达式与性能:
- CASE WHEN 表达式(SELECT 列/WHERE/聚合)
- JOIN + 关联子查询逐行绑定
- WAL 批量组提交(写放大 O(N)→O(1))
- 修复 pending frozen 可见性 + flush 缓存竞争

v0.3.2 并发:
- CASE WHEN 用于 WHERE/聚合 + JOIN 哈希连接
- 多标签页同步(multiTabSync + BroadcastChannel)
- IndexedDB schema 持久化(reopen 后表结构恢复)
- 修复 where-matcher 顶层 $not
- 修复 CJS 产物 .js 被 ESM 解析(exports 空) — .cjs 后缀 + exports 修正
- 836 测试 / 44 套件 / 81.0% 覆盖率
2026-08-08 10:41:30 +08:00

337 lines
21 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Changelog
All notable changes to MetonaSqlark will be documented in this file.
## [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 JOINO(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_schema` store 保存完整列定义,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 dependencyrollup 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.ts` VERSION 从 `'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` / Vue `useSqlarkTable` 增加表名合法性校验(`/^[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` ...
### 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 在事务中缓冲到 snapshotcommit 批量写入 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()` 递归解析,自动执行子查询并替换为具体值
- **外键级联操作**: ColumnDef 新增 `onDelete/onUpdate` 选项
- 支持 `CASCADE`(递归级联删除)、`SET NULL``RESTRICT`
- SQL Parser 解析 `REFERENCES table(col) ON DELETE CASCADE ON UPDATE CASCADE`
- MemoryEngine 内置 `cascadeDelete()` 递归级联逻辑
- **连接池管理**: `MetonaSqlark.connect()` 静态方法
- 同名数据库复用已打开实例,引用计数管理
- `db.disconnect()` 释放连接,归零自动 close
- `MetonaSqlark.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.js` CommonJS 构建产物
- 完善的 `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