release: v0.3.2 — 质量加固 + SQL扩展 + 表达式 + 并发同步
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

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% 覆盖率
This commit is contained in:
thzxx
2026-08-08 10:41:30 +08:00
parent 3ae7d6e8fb
commit d544501e1c
77 changed files with 29007 additions and 20395 deletions
+275 -209
View File
@@ -1,209 +1,275 @@
/**
* metona-sqlark Query AST — 查询抽象语法树类型定义
* @module query/ast
*
* QueryBuilder 和 SQL Parser 统一输出此 AST
* Executor 只认 AST,保证两种查询接口行为一致。
*/
import type { WhereCondition, OrderBy } from '../constants';
// ---------------------------------------------------------------------------
// AST 语句类型枚举
// ---------------------------------------------------------------------------
export type StatementType =
| 'SELECT'
| 'EXPLAIN'
| 'INSERT'
| 'UPDATE'
| 'DELETE'
| 'CREATE_TABLE'
| 'DROP_TABLE'
| 'ALTER_TABLE'
| 'TRUNCATE_TABLE';
// ---------------------------------------------------------------------------
// 列引用
// ---------------------------------------------------------------------------
/** 列引用,'*' 表示所有列;支持 'table.column' 格式 */
export type ColumnRef = string;
// ---------------------------------------------------------------------------
// JOIN
// ---------------------------------------------------------------------------
/** JOIN 类型 */
export type JoinType = 'INNER' | 'LEFT' | 'RIGHT' | 'CROSS';
/** JOIN 子句 */
export interface JoinClause {
type: JoinType;
table: string;
alias?: string;
on: WhereCondition;
}
// ---------------------------------------------------------------------------
// 聚合函数
// ---------------------------------------------------------------------------
/** 聚合函数类型 */
export type AggregateFunc = 'COUNT' | 'SUM' | 'AVG' | 'MIN' | 'MAX';
/** 聚合表达式 */
export interface AggregateExpression {
type: 'AGGREGATE';
func: AggregateFunc;
column: string; // '*' for COUNT(*)
alias?: string;
}
// ---------------------------------------------------------------------------
// 子查询
// ---------------------------------------------------------------------------
/** 子查询表达式 */
export interface SubqueryExpression {
type: 'SUBQUERY';
statement: SelectStatement;
}
// ---------------------------------------------------------------------------
// DDL: CREATE TABLE
// ---------------------------------------------------------------------------
export interface ASTColumnDef {
name: string;
type: string;
primaryKey?: boolean;
unique?: boolean;
required?: boolean;
default?: unknown;
index?: boolean;
maxLength?: number;
min?: number;
max?: number;
/** 外键引用 */
references?: string;
/** 级联删除 */
onDelete?: 'CASCADE' | 'SET NULL' | 'RESTRICT';
/** 级联更新 */
onUpdate?: 'CASCADE' | 'SET NULL' | 'RESTRICT';
}
export interface CreateTableStatement {
type: 'CREATE_TABLE';
name: string;
columns: ASTColumnDef[];
/** IF NOT EXISTS — 表已存在时不报错 */
ifNotExists?: boolean;
}
// ---------------------------------------------------------------------------
// DDL: DROP TABLE
// ---------------------------------------------------------------------------
export interface DropTableStatement {
type: 'DROP_TABLE';
name: string;
/** IF EXISTS — 表不存在时不报错 */
ifExists?: boolean;
}
/** EXPLAIN 查询计划 */
export interface ExplainStatement {
type: 'EXPLAIN';
query: Statement;
}
// ---------------------------------------------------------------------------
// DML: INSERT
// ---------------------------------------------------------------------------
export interface InsertStatement {
type: 'INSERT';
into: string;
columns?: string[];
values: unknown[][];
}
// ---------------------------------------------------------------------------
// DML: UPDATE
// ---------------------------------------------------------------------------
export interface UpdateStatement {
type: 'UPDATE';
table: string;
sets: Record<string, unknown>;
where: WhereCondition;
}
// ---------------------------------------------------------------------------
// DML: DELETE
// ---------------------------------------------------------------------------
export interface DeleteStatement {
type: 'DELETE';
from: string;
where: WhereCondition;
}
// ---------------------------------------------------------------------------
// DQL: SELECT
// ---------------------------------------------------------------------------
export interface SelectStatement {
type: 'SELECT';
columns: ColumnRef[];
distinct?: boolean;
from: string;
/** 主表别名 */
alias?: string;
/** JOIN 子句列表 */
joins?: JoinClause[];
where: WhereCondition;
/** GROUP BY */
groupBy?: string[];
/** HAVING */
having?: WhereCondition;
orderBy?: OrderBy[];
limit?: number;
offset?: number;
}
// ---------------------------------------------------------------------------
// DDL: ALTER TABLE
// ---------------------------------------------------------------------------
export interface AlterTableStatement {
type: 'ALTER_TABLE';
name: string;
action: 'ADD' | 'DROP';
column: ASTColumnDef;
}
// ---------------------------------------------------------------------------
// DDL: TRUNCATE TABLE
// ---------------------------------------------------------------------------
export interface TruncateTableStatement {
type: 'TRUNCATE_TABLE';
name: string;
}
// ---------------------------------------------------------------------------
// AST 联合类型
// ---------------------------------------------------------------------------
export type Statement =
| SelectStatement
| ExplainStatement
| InsertStatement
| UpdateStatement
| DeleteStatement
| CreateTableStatement
| DropTableStatement
| AlterTableStatement
| TruncateTableStatement;
/**
* metona-sqlark Query AST — 查询抽象语法树类型定义
* @module query/ast
*
* QueryBuilder 和 SQL Parser 统一输出此 AST
* Executor 只认 AST,保证两种查询接口行为一致。
*/
import type { WhereCondition, OrderBy } from '../constants';
// ---------------------------------------------------------------------------
// AST 语句类型枚举
// ---------------------------------------------------------------------------
export type StatementType =
| 'SELECT'
| 'SELECT_UNION'
| 'EXPLAIN'
| 'INSERT'
| 'UPDATE'
| 'DELETE'
| 'CREATE_TABLE'
| 'DROP_TABLE'
| 'ALTER_TABLE'
| 'TRUNCATE_TABLE'
| 'CREATE_INDEX'
| 'DROP_INDEX'
| 'BEGIN'
| 'COMMIT'
| 'ROLLBACK';
// ---------------------------------------------------------------------------
// 列引用
// ---------------------------------------------------------------------------
/** 列引用,'*' 表示所有列;支持 'table.column' 格式 */
export type ColumnRef = string;
// ---------------------------------------------------------------------------
// JOIN
// ---------------------------------------------------------------------------
/** JOIN 类型 */
export type JoinType = 'INNER' | 'LEFT' | 'RIGHT' | 'CROSS';
/** JOIN 子句 */
export interface JoinClause {
type: JoinType;
table: string;
alias?: string;
on: WhereCondition;
}
// ---------------------------------------------------------------------------
// 聚合函数
// ---------------------------------------------------------------------------
/** 聚合函数类型 */
export type AggregateFunc = 'COUNT' | 'SUM' | 'AVG' | 'MIN' | 'MAX';
/** 聚合表达式 */
export interface AggregateExpression {
type: 'AGGREGATE';
func: AggregateFunc;
column: string; // '*' for COUNT(*)
alias?: string;
}
// ---------------------------------------------------------------------------
// 子查询
// ---------------------------------------------------------------------------
/** 子查询表达式 */
export interface SubqueryExpression {
type: 'SUBQUERY';
statement: SelectStatement | SelectUnionStatement;
}
// ---------------------------------------------------------------------------
// DDL: CREATE TABLE
// ---------------------------------------------------------------------------
export interface ASTColumnDef {
name: string;
type: string;
primaryKey?: boolean;
unique?: boolean;
required?: boolean;
default?: unknown;
index?: boolean;
maxLength?: number;
min?: number;
max?: number;
/** 外键引用 */
references?: string;
/** 级联删除 */
onDelete?: 'CASCADE' | 'SET NULL' | 'RESTRICT';
/** 级联更新 */
onUpdate?: 'CASCADE' | 'SET NULL' | 'RESTRICT';
}
export interface CreateTableStatement {
type: 'CREATE_TABLE';
name: string;
columns: ASTColumnDef[];
/** IF NOT EXISTS — 表已存在时不报错 */
ifNotExists?: boolean;
}
// ---------------------------------------------------------------------------
// DDL: DROP TABLE
// ---------------------------------------------------------------------------
export interface DropTableStatement {
type: 'DROP_TABLE';
name: string;
/** IF EXISTS — 表不存在时不报错 */
ifExists?: boolean;
}
/** EXPLAIN 查询计划 */
export interface ExplainStatement {
type: 'EXPLAIN';
query: Statement;
}
// ---------------------------------------------------------------------------
// DML: INSERT
// ---------------------------------------------------------------------------
export interface InsertStatement {
type: 'INSERT';
into: string;
columns?: string[];
/** VALUES 字面量 */
values?: unknown[][];
/** INSERT INTO ... SELECT ...v0.3.0 */
select?: SelectStatement | SelectUnionStatement;
}
// ---------------------------------------------------------------------------
// DML: UPDATE
// ---------------------------------------------------------------------------
export interface UpdateStatement {
type: 'UPDATE';
table: string;
sets: Record<string, unknown>;
where: WhereCondition;
}
// ---------------------------------------------------------------------------
// DML: DELETE
// ---------------------------------------------------------------------------
export interface DeleteStatement {
type: 'DELETE';
from: string;
where: WhereCondition;
}
// ---------------------------------------------------------------------------
// DQL: SELECT
// ---------------------------------------------------------------------------
export interface SelectStatement {
type: 'SELECT';
columns: ColumnRef[];
distinct?: boolean;
from: string;
/** 主表别名 */
alias?: string;
/** JOIN 子句列表 */
joins?: JoinClause[];
where: WhereCondition;
/** GROUP BY */
groupBy?: string[];
/** HAVING */
having?: WhereCondition;
orderBy?: OrderBy[];
limit?: number;
offset?: number;
}
// ---------------------------------------------------------------------------
// DQL: UNION
// ---------------------------------------------------------------------------
export interface SelectUnionStatement {
type: 'SELECT_UNION';
/** 左操作数(可以是 SELECT 或嵌套 UNION */
left: SelectStatement | SelectUnionStatement;
/** 右操作数 */
right: SelectStatement | SelectUnionStatement;
/** UNION ALL 不去重 */
all?: boolean;
}
// ---------------------------------------------------------------------------
// DDL: ALTER TABLE
// ---------------------------------------------------------------------------
export interface AlterTableStatement {
type: 'ALTER_TABLE';
name: string;
action: 'ADD' | 'DROP';
column: ASTColumnDef;
}
// ---------------------------------------------------------------------------
// DDL: TRUNCATE TABLE
// ---------------------------------------------------------------------------
export interface TruncateTableStatement {
type: 'TRUNCATE_TABLE';
name: string;
}
// ---------------------------------------------------------------------------
// DDL: CREATE INDEX / DROP INDEXv0.3.0
// ---------------------------------------------------------------------------
export interface CreateIndexStatement {
type: 'CREATE_INDEX';
/** 索引名(语法占位) */
name: string;
table: string;
column: string;
/** UNIQUE 索引 */
unique?: boolean;
}
export interface DropIndexStatement {
type: 'DROP_INDEX';
name: string;
table: string;
column: string;
}
// ---------------------------------------------------------------------------
// TCL: 事务语句(v0.3.0
// ---------------------------------------------------------------------------
export interface BeginTransactionStatement {
type: 'BEGIN';
}
export interface CommitTransactionStatement {
type: 'COMMIT';
}
export interface RollbackTransactionStatement {
type: 'ROLLBACK';
}
// ---------------------------------------------------------------------------
// AST 联合类型
// ---------------------------------------------------------------------------
export type Statement =
| SelectStatement
| SelectUnionStatement
| ExplainStatement
| InsertStatement
| UpdateStatement
| DeleteStatement
| CreateTableStatement
| DropTableStatement
| AlterTableStatement
| TruncateTableStatement
| CreateIndexStatement
| DropIndexStatement
| BeginTransactionStatement
| CommitTransactionStatement
| RollbackTransactionStatement;
+16 -4
View File
@@ -134,12 +134,16 @@ export class SelectQueryBuilder {
export class UpdateQueryBuilder {
private _where: WhereCondition = {};
private onWrite?: (table: string) => void;
constructor(
private engine: IStorageEngine,
private tableName: string,
private _updates: Record<string, unknown>,
) {}
onWrite?: (table: string) => void,
) {
this.onWrite = onWrite;
}
where(condition: WhereCondition): this {
this._where = { ...this._where, ...condition };
@@ -147,7 +151,9 @@ export class UpdateQueryBuilder {
}
async execute(): Promise<number> {
return this.engine.update(this.tableName, { table: this.tableName, where: this._where }, this._updates);
const count = await this.engine.update(this.tableName, { table: this.tableName, where: this._where }, this._updates);
this.onWrite?.(this.tableName);
return count;
}
toAST(): UpdateStatement {
@@ -161,11 +167,15 @@ export class UpdateQueryBuilder {
export class DeleteQueryBuilder {
private _where: WhereCondition = {};
private onWrite?: (table: string) => void;
constructor(
private engine: IStorageEngine,
private tableName: string,
) {}
onWrite?: (table: string) => void,
) {
this.onWrite = onWrite;
}
where(condition: WhereCondition): this {
this._where = { ...this._where, ...condition };
@@ -173,7 +183,9 @@ export class DeleteQueryBuilder {
}
async execute(): Promise<number> {
return this.engine.delete(this.tableName, { table: this.tableName, where: this._where });
const count = await this.engine.delete(this.tableName, { table: this.tableName, where: this._where });
this.onWrite?.(this.tableName);
return count;
}
toAST(): DeleteStatement {
+1061 -448
View File
File diff suppressed because it is too large Load Diff
+15
View File
@@ -42,6 +42,16 @@ export function matchWhere(
options: { $col?: boolean } = {},
): boolean {
for (const [field, condition] of Object.entries(where)) {
// 顶层 $caseResultv0.3.2):由 Executor 对 CASE WHEN 表达式逐行求值后产生
if (field === '$caseResult') {
if (condition !== true) return false;
continue;
}
// 顶层 $existsv0.3.0):由 Executor.resolveSubqueries 解析为 boolean
if (field === '$exists') {
if (condition !== true) return false;
continue;
}
// 顶层 $and
if (field === '$and') {
const subs = condition as WhereCondition[];
@@ -54,6 +64,11 @@ export function matchWhere(
if (!subs.some((sub) => matchWhere(row, sub, options))) return false;
continue;
}
// 顶层 $notv0.3.2 修复:NOT (expr) 生成的 { $not: inner }
if (field === '$not') {
if (matchWhere(row, condition as WhereCondition, options)) return false;
continue;
}
if (!matchField(row[field], condition, row, options)) return false;
}
return true;