Files
MetonaSqlark/dist/metona-sqlark.d.ts
T
thzxx a1e4f5071c
CI / test (20.x) (push) Successful in 10m4s
CI / test (22.x) (push) Successful in 10m8s
CI / test (24.x) (push) Successful in 9m55s
CI / test (18.x) (push) Successful in 10m9s
release: v0.4.1 — Aria 级联/ALTER/clearAll + 流式查询/派生表 + 正确性加固
新增:
- AriaEngine 外键级联(CASCADE/SET NULL/RESTRICT)+ clearAll() 重置 API
- 引擎级 alterTable:Aria DROP COLUMN 重写存储行 + schema 持久化
- 流式查询 queryStream / findStream(LSM 惰性扫描不物化)
- FROM 派生表 / 多列 ON 哈希连接 / COUNT(DISTINCT) / NULLS FIRST/LAST
- 普通列别名 + ORDER BY 别名 + 无表查询 + 字符串常量列
- 演示页引擎切换器(Memory/Aria)+ 预设自动重置

修复:
- Aria WAL DROP_TABLE 崩溃恢复(删表复活)+ 恢复后 WAL 截断
- Memory update/delete 索引维护(unique 约束绕过)
- 关联 EXISTS 绑定失效 / HAVING 标量子查询 / INSERT SELECT 位置错位
- 裸布尔列条件(WHERE done / CASE WHEN done)
- Aria $in 重复行 / JOIN 主表 WHERE 下推 / DROP INDEX 报错
- ORDER BY/GROUP BY/SELECT 表前缀列 + SQL '' 标准转义

质量:894 测试 · 47 套件 · 81.5% 覆盖率
2026-08-08 13:36:34 +08:00

1262 lines
43 KiB
TypeScript
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.
/**
* metona-sqlark Constants — 类型定义 / 默认配置 / 枚举
* @module constants
*/
/** 存储模式 */
type StorageMode = 'memory' | 'disk' | 'hybrid' | 'aria';
/** 磁盘引擎类型 */
type DiskEngine = 'indexeddb' | 'opfs';
/** 字段数据类型 */
type FieldType = 'string' | 'number' | 'boolean' | 'date' | 'json';
/** 列定义 */
interface ColumnDef {
/** 字段类型 */
type: FieldType;
/** 是否主键 */
primaryKey?: boolean;
/** 是否必填 */
required?: boolean;
/** 是否唯一 */
unique?: boolean;
/** 默认值 */
default?: unknown;
/** 是否创建索引 */
index?: boolean;
/** 外键引用: 'table.column' */
references?: string;
/** 删除级联: 'CASCADE' | 'SET NULL' | 'RESTRICT' */
onDelete?: 'CASCADE' | 'SET NULL' | 'RESTRICT';
/** 更新级联: 'CASCADE' | 'SET NULL' | 'RESTRICT' */
onUpdate?: 'CASCADE' | 'SET NULL' | 'RESTRICT';
/** 字符串最大长度 */
maxLength?: number;
/** 数字最小值 */
min?: number;
/** 数字最大值 */
max?: number;
}
/** 表结构定义 */
interface TableSchema {
/** 表名 */
name: string;
/** 列定义映射 */
columns: Record<string, ColumnDef>;
}
/** 数据库配置 */
interface DatabaseConfig {
/** 数据库名称 */
name: string;
/** 存储模式 */
mode?: StorageMode;
/** 磁盘引擎(仅 mode='disk'|'hybrid' 时生效) */
diskEngine?: DiskEngine;
/** 版本号 */
version?: number;
/** 插件列表 */
plugins?: MetonaPlugin[];
/** 数据库就绪回调 */
onReady?: (db: unknown) => void;
/** 错误回调 */
onError?: (error: Error) => void;
/** 查询结果行数上限(默认 0,0 表示不限制) */
maxRowsPerQuery?: number;
/** 调试模式(启用后输出详细操作日志) */
debug?: boolean;
/** 多标签页同步(v0.3.2):BroadcastChannel 广播表变更,其他标签页自动刷新 */
multiTabSync?: boolean;
}
/** Where 条件操作符 */
type WhereOperator = '$eq' | '$ne' | '$gt' | '$gte' | '$lt' | '$lte' | '$in' | '$nin' | '$like' | '$and' | '$or' | '$not';
/** 简单条件值:直接相等 */
type SimpleCondition = unknown;
/** 操作符条件 */
type OperatorCondition = Partial<Record<WhereOperator, unknown>>;
/** 字段条件:简单值 | 操作符对象 */
type FieldCondition = SimpleCondition | OperatorCondition;
/** Where 条件对象 */
type WhereCondition = Record<string, FieldCondition>;
/** 排序方向 */
type SortDirection = 'asc' | 'desc';
/** 排序定义 */
interface OrderBy {
/** 列名 */
column: string;
/** 排序方向 */
direction: SortDirection;
/** v0.4.0: NULL 值排序位置(first 排最前 / last 排最后,默认同引擎行为) */
nulls?: 'first' | 'last';
}
/** 查询计划 — 由 Executor 编译 AST 后生成 */
interface QueryPlan {
/** 表名 */
table: string;
/** 要返回的列(undefined = 全部,['*'] = 全部) */
columns?: string[];
/** 过滤条件 */
where?: WhereCondition;
/** 排序 */
orderBy?: OrderBy[];
/** 限制条数 */
limit?: number;
/** 偏移量 */
offset?: number;
}
/** 钩子名称 */
type HookName = 'beforeCreateTable' | 'afterCreateTable' | 'beforeDropTable' | 'afterDropTable' | 'beforeInsert' | 'afterInsert' | 'beforeUpdate' | 'afterUpdate' | 'beforeDelete' | 'afterDelete' | 'beforeQuery' | 'afterQuery' | 'beforeTransaction' | 'afterTransaction';
/** 插件定义 */
interface MetonaPlugin {
/** 插件名称 */
name: string;
/** 插件版本 */
version: string;
/** 描述 */
description?: string;
/** 优先级,越大越先执行 */
priority?: number;
/** 安装 */
install(db: unknown): void;
/** 销毁 */
destroy(): void;
}
declare const VERSION = "0.4.1";
/**
* metona-sqlark Plugin — 插件系统
* @module plugin
*
* 管理插件的注册、生命周期和钩子调度。
*/
type HookCallback = (...args: unknown[]) => void | Promise<void>;
declare class PluginManager {
private plugins;
private hooks;
/** 注册插件 */
register(plugin: MetonaPlugin, db?: unknown): void;
/** 卸载插件 */
unregister(pluginName: string): void;
/** 获取所有已注册插件 */
getPlugins(): MetonaPlugin[];
/** 添加钩子回调 */
on(hook: HookName, callback: HookCallback): void;
/** 移除钩子回调 */
off(hook: HookName, callback: HookCallback): void;
/** 触发钩子 */
trigger(hook: HookName, ...args: unknown[]): Promise<void>;
/** 销毁所有插件 */
destroy(): void;
}
interface IStorageEngine {
/** 引擎名称 */
readonly name: string;
/** 打开数据库 */
open(dbName: string, version: number): Promise<void>;
/** 关闭数据库 */
close(): Promise<void>;
/** 检查数据库是否已打开 */
isOpen(): boolean;
/** 创建表 */
createTable(schema: TableSchema): Promise<void>;
/** 删除表 */
dropTable(tableName: string): Promise<void>;
/** 检查表是否存在 */
hasTable(tableName: string): Promise<boolean>;
/** 获取所有表名 */
getTableNames(): Promise<string[]>;
/** 获取表结构 */
getTableSchema(tableName: string): Promise<TableSchema | null>;
/** 插入行,返回主键值列表 */
insert(tableName: string, rows: Record<string, unknown>[]): Promise<string[]>;
/** 查询行 */
find(tableName: string, query: QueryPlan): Promise<Record<string, unknown>[]>;
/** v0.4.0: 流式查询 — 逐行回调扫描(有 where/limit/projection,无 orderBy 语义;有 orderBy 时实现可回退物化) */
findStream?(tableName: string, query: QueryPlan, onRow: (row: Record<string, unknown>) => void): Promise<number>;
/** 更新行,返回影响行数 */
update(tableName: string, query: QueryPlan, updates: Record<string, unknown>): Promise<number>;
/** 删除行,返回影响行数 */
delete(tableName: string, query: QueryPlan): Promise<number>;
/** 计数 */
count(tableName: string, query?: QueryPlan): Promise<number>;
/** 清空表数据(保留结构) */
clear(tableName: string): Promise<void>;
/** v0.4.1: ALTER TABLE(可选)— 引擎级结构变更(Aria 需重写存储行,其余引擎走 Executor 通用路径) */
alterTable?(tableName: string, action: 'ADD' | 'DROP', column: ColumnDef & {
name: string;
}): Promise<void>;
/** 创建二级索引(CREATE INDEX */
createIndex?(tableName: string, column: string, unique?: boolean): Promise<void>;
/** 删除二级索引(DROP INDEX */
dropIndex?(tableName: string, column: string, indexName?: string): Promise<void>;
/** 开始事务 */
beginTransaction(): Promise<void>;
/** 提交事务 */
commitTransaction(): Promise<void>;
/** 回滚事务 */
rollbackTransaction(): Promise<void>;
/** 创建 Savepoint */
savepoint?(name: string): Promise<void>;
/** 回滚到 Savepoint */
rollbackToSavepoint?(name: string): Promise<void>;
/** 释放 Savepoint */
releaseSavepoint?(name: string): Promise<void>;
/** 在线备份:导出全库一致性快照 */
backup?(): Promise<Record<string, Record<string, unknown>[]>>;
}
/**
* metona-sqlark Query AST — 查询抽象语法树类型定义
* @module query/ast
*
* QueryBuilder 和 SQL Parser 统一输出此 AST
* Executor 只认 AST,保证两种查询接口行为一致。
*/
/** 列引用,'*' 表示所有列;支持 'table.column' 格式 */
type ColumnRef = string;
/** JOIN 类型 */
type JoinType = 'INNER' | 'LEFT' | 'RIGHT' | 'CROSS';
/** JOIN 子句 */
interface JoinClause {
type: JoinType;
table: string;
alias?: string;
on: WhereCondition;
}
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';
}
interface CreateTableStatement {
type: 'CREATE_TABLE';
name: string;
columns: ASTColumnDef[];
/** IF NOT EXISTS — 表已存在时不报错 */
ifNotExists?: boolean;
}
interface DropTableStatement {
type: 'DROP_TABLE';
name: string;
/** IF EXISTS — 表不存在时不报错 */
ifExists?: boolean;
}
/** EXPLAIN 查询计划 */
interface ExplainStatement {
type: 'EXPLAIN';
query: Statement;
}
interface InsertStatement {
type: 'INSERT';
into: string;
columns?: string[];
/** VALUES 字面量 */
values?: unknown[][];
/** INSERT INTO ... SELECT ...v0.3.0 */
select?: SelectStatement | SelectUnionStatement;
}
interface UpdateStatement {
type: 'UPDATE';
table: string;
sets: Record<string, unknown>;
where: WhereCondition;
}
interface DeleteStatement {
type: 'DELETE';
from: string;
where: WhereCondition;
}
interface SelectStatement {
type: 'SELECT';
columns: ColumnRef[];
distinct?: boolean;
from: string;
/** v0.4.0: FROM (SELECT ...) 派生表(存在时 from 为占位,行源取此子查询结果) */
fromSubquery?: SelectStatement | SelectUnionStatement;
/** 主表别名 */
alias?: string;
/** JOIN 子句列表 */
joins?: JoinClause[];
where: WhereCondition;
/** GROUP BY */
groupBy?: string[];
/** HAVING */
having?: WhereCondition;
orderBy?: OrderBy[];
limit?: number;
offset?: number;
}
interface SelectUnionStatement {
type: 'SELECT_UNION';
/** 左操作数(可以是 SELECT 或嵌套 UNION */
left: SelectStatement | SelectUnionStatement;
/** 右操作数 */
right: SelectStatement | SelectUnionStatement;
/** UNION ALL 不去重 */
all?: boolean;
}
interface AlterTableStatement {
type: 'ALTER_TABLE';
name: string;
action: 'ADD' | 'DROP';
column: ASTColumnDef;
}
interface TruncateTableStatement {
type: 'TRUNCATE_TABLE';
name: string;
}
interface CreateIndexStatement {
type: 'CREATE_INDEX';
/** 索引名(语法占位) */
name: string;
table: string;
column: string;
/** UNIQUE 索引 */
unique?: boolean;
}
interface DropIndexStatement {
type: 'DROP_INDEX';
name: string;
table: string;
column: string;
}
interface BeginTransactionStatement {
type: 'BEGIN';
}
interface CommitTransactionStatement {
type: 'COMMIT';
}
interface RollbackTransactionStatement {
type: 'ROLLBACK';
}
type Statement = SelectStatement | SelectUnionStatement | ExplainStatement | InsertStatement | UpdateStatement | DeleteStatement | CreateTableStatement | DropTableStatement | AlterTableStatement | TruncateTableStatement | CreateIndexStatement | DropIndexStatement | BeginTransactionStatement | CommitTransactionStatement | RollbackTransactionStatement;
/**
* metona-sqlark Query Executor — AST 执行器
* @module query/executor
*
* JOIN / GROUP BY / DISTINCT 逻辑在此层处理。
*/
declare class QueryExecutor {
private engine;
private maxRowsPerQuery;
constructor(engine: IStorageEngine, maxRowsPerQuery?: number);
/** 设置查询结果行数上限 */
setMaxRowsPerQuery(max: number): void;
execute(stmt: Statement): Promise<unknown>;
/** 递归执行 UNION / UNION ALL,返回合并结果 */
private executeSelectUnion;
private executeSelectPart;
/** 将 UNION 右侧行投影为左侧列结构(按位置取值) */
private projectUnionRow;
/** EXPLAIN: 输出查询计划 */
private executeExplain;
private executeSelect;
private executeJoinSelect;
private prefixRow;
/**
* v0.4.1: 提取可下推的 WHERE 条件 — 主表别名前缀的普通条件(如 o.user_id = '1')。
* 下推到引擎可走二级索引;$col/$subquery/$and/$or/$not 等复杂条件保守不下推。
*/
private extractPushableWhere;
/**
* 哈希连接(v0.3.2 单等值 / v0.4.0 多列等值):
* ON 为等值条件(单列或多列)且右表任一列为索引/主键时,
* 收集左表连接值 → 一次 $in 查询右表 → 哈希映射匹配。
* 替代嵌套循环,大表 INNER/LEFT JOIN 复杂度 O(N + M)。
* 不适用时返回 null(回退嵌套循环)。
*/
private tryHashJoin;
/** 嵌套循环连接(优化:避免 ON 时对象扩散) */
private joinRows;
private executeGroupBy;
private computeAggregate;
private executeDistinct;
private executeInsert;
private executeUpdate;
private executeDelete;
private executeCreateTable;
private executeDropTable;
private executeAlterTable;
private executeTruncateTable;
private executeCreateIndex;
private executeDropIndex;
private executeBegin;
private executeCommit;
private executeRollback;
/** 列列表是否包含 CASE WHEN 表达式 */
private hasCaseColumn;
/**
* v0.3.3: ORDER BY 是否引用 SELECT 别名(如 `SELECT name AS n ... ORDER BY n`)。
* 别名列在引擎层投影前不存在,需投影后重新排序。
*/
private orderByUsesSelectAlias;
/** WHERE 是否包含 CASE WHEN 表达式键 */
private whereHasCase;
getEngine(): IStorageEngine;
/**
* 列投影(v0.3.1):普通列走 projectColumnsCASE WHEN 表达式逐行求值;
* v0.3.3: 支持 `col AS alias` 列别名
*/
private projectRow;
/** 检查 SELECT 列列表中是否包含聚合函数 */
private _hasAggregateColumn;
/** 计算单行聚合结果(无 GROUP BY) */
private computeSingleAggregate;
/** 剥离主表别名前缀:'u.id' → 'id'(键与 $col 值均处理,支持多层别名) */
private normalizeWhereColumns;
private normalizeExistsValue;
private normalizeFieldValue;
private stripAlias;
/** WHERE 是否含关联引用($col 或关联 EXISTS)或 CASE WHEN 表达式键 */
private hasCorrelatedRefs;
private fieldHasColRef;
/** 移除关联 EXISTS 标记(引擎层先执行无 EXISTS 条件的查询) */
private stripCorrelatedExists;
/** 逐行绑定外层行上下文,求值关联 EXISTS、$col 引用与 CASE WHEN 键 */
private filterCorrelated;
/** 将 WHERE 中的 CASE WHEN 表达式键求值为布尔条件($caseResult */
private resolveCaseKeys;
/** CASE 求值结果与操作符条件比较 */
private caseConditionMatches;
/** 将 where 中的 $col 引用替换为上下文行值 */
private bindColumnRefs;
private bindWhereRefs;
/**
* 递归扫描 WHERE 条件,找到 $subquery 标记并执行子查询,
* 将结果替换为具体值。
* @param contextRow 关联子查询的外层行上下文(用于绑定 $col 引用)
*/
private resolveSubqueries;
/**
* 解析操作符值中嵌套的子查询
*/
private resolveOperatorSubqueries;
}
/**
* metona-sqlark Query Builder — 链式查询构建器
* @module query/builder
*
* 链式调用 → 构建 AST → 执行引擎操作。
* 支持 JOIN(需要 Executor)。
*/
declare class SelectQueryBuilder {
private engine;
private tableName;
private _columns;
private _where;
private _orderBy;
private _limit?;
private _offset?;
private _joins;
private _alias?;
private _executor?;
constructor(engine: IStorageEngine, tableName: string, _columns?: string[], executor?: QueryExecutor);
/** 主表别名 */
as(alias: string): this;
/** INNER JOIN */
innerJoin(table: string, on: WhereCondition, alias?: string): this;
/** LEFT JOIN */
leftJoin(table: string, on: WhereCondition, alias?: string): this;
/** RIGHT JOIN */
rightJoin(table: string, on: WhereCondition, alias?: string): this;
/** CROSS JOIN */
crossJoin(table: string, alias?: string): this;
/** 通用 JOIN */
join(table: string, on: WhereCondition, alias?: string): this;
private _addJoin;
/** 添加过滤条件 */
where(condition: WhereCondition): this;
/** 排序 */
orderBy(column: string, direction?: SortDirection): this;
/** 限制返回条数 */
limit(n: number): this;
/** 偏移量 */
offset(n: number): this;
/** 执行查询 */
execute(): Promise<Record<string, unknown>[]>;
/** 获取 AST */
toAST(): SelectStatement;
}
declare class UpdateQueryBuilder {
private engine;
private tableName;
private _updates;
private _where;
private onWrite?;
constructor(engine: IStorageEngine, tableName: string, _updates: Record<string, unknown>, onWrite?: (table: string) => void);
where(condition: WhereCondition): this;
execute(): Promise<number>;
toAST(): UpdateStatement;
}
declare class DeleteQueryBuilder {
private engine;
private tableName;
private _where;
private onWrite?;
constructor(engine: IStorageEngine, tableName: string, onWrite?: (table: string) => void);
where(condition: WhereCondition): this;
execute(): Promise<number>;
toAST(): DeleteStatement;
}
/**
* metona-sqlark Table — 表操作 API
* @module table/table
*/
declare class Table<T = Record<string, unknown>> {
readonly name: string;
private engine;
private schema;
private executor;
/** 写入回调(多标签页广播,v0.3.2) */
private onWrite?;
constructor(engine: IStorageEngine, tableName: string, executor?: QueryExecutor, onWrite?: (table: string) => void);
getSchema(): Promise<TableSchema>;
insert(row: T & Record<string, unknown>): Promise<string>;
insertMany(rows: (T & Record<string, unknown>)[]): Promise<string[]>;
select(columns?: string[]): SelectQueryBuilder;
/** v0.4.0: 流式查询 — 逐行回调,不物化全部结果 */
stream(onRow: (row: T & Record<string, unknown>) => void, query?: {
where?: Record<string, unknown>;
limit?: number;
offset?: number;
columns?: string[];
}): Promise<number>;
update(updates: Partial<T> & Record<string, unknown>): UpdateQueryBuilder;
delete(): DeleteQueryBuilder;
count(where?: Record<string, unknown>): Promise<number>;
clear(): Promise<void>;
drop(): Promise<void>;
}
/**
* metona-sqlark Transaction — 事务管理
* @module transaction
*
* v0.1.13: 支持真正的回滚 — 利用引擎层 begin/commit/rollback 实现原子性。
*/
declare class Transaction {
private engine;
private tables;
private completed;
constructor(engine: IStorageEngine);
/** 获取表操作对象 */
table(tableName: string): Table;
/** 标记事务完成(由 TransactionManager 调用) */
_markCompleted(): void;
/** 是否已完成 */
isCompleted(): boolean;
}
declare class MetonaSqlark {
/** 数据库名称 */
readonly name: string;
/** 存储模式 */
readonly mode: string;
/** 版本号 */
private _version;
/** 获取版本号 */
get version(): number;
private engine;
private executor;
private transactionManager;
private pluginManager;
private config;
private ready;
private tableCache;
/** 查询结果行数上限 */
get maxRowsPerQuery(): number;
/** 调试模式 */
get debug(): boolean;
/** 多标签页同步通道(v0.3.2 */
private channel;
constructor(config: DatabaseConfig);
/** 初始化数据库(创建引擎、打开连接) */
init(): Promise<void>;
/** 检查是否就绪 */
isReady(): boolean;
/** 创建表 */
defineTable(name: string, columns: Record<string, ColumnDef>): Promise<void>;
/** 获取表操作对象 */
table(name: string): Table;
/** 删除表 */
dropTable(name: string): Promise<void>;
/** 获取所有表名 */
getTableNames(): Promise<string[]>;
/** 执行 SQL 字符串查询 */
query(sql: string): Promise<unknown>;
/**
* 流式查询:逐行回调,不一次性物化全部结果(大表友好)。
* 支持简单 SELECTWHERE/LIMIT/OFFSET/列投影);
* JOIN/GROUP BY/UNION/聚合/ORDER BY 自动回退为物化查询后逐行回调。
*
* @example
* ```ts
* let total = 0;
* await db.queryStream('SELECT * FROM logs WHERE level = \'error\'', (row) => {
* total++;
* processRow(row);
* });
* ```
*/
queryStream<T extends Record<string, unknown> = Record<string, unknown>>(sql: string, onRow: (row: T) => void): Promise<number>;
/** 流式查询用:剥离主表别名前缀(复用 query 路径的规范化逻辑) */
private normalizeWhereForStream;
/** 执行事务 */
transaction<T>(fn: (trx: Transaction) => Promise<T>): Promise<T>;
/** 导出表数据为 JSON */
exportTable(tableName: string): Promise<Record<string, unknown>[]>;
/** 导入 JSON 数据到表 */
importTable(tableName: string, data: Record<string, unknown>[]): Promise<string[]>;
/** 导出整个数据库为 JSON */
exportAll(): Promise<Record<string, Record<string, unknown>[]>>;
private listeners;
/** 订阅表变更 */
subscribe(tableName: string, callback: (event: {
type: string;
row?: unknown;
table?: string;
}) => void): () => void;
/** 触发变更事件 */
emit(tableName: string, event: {
type: string;
row?: unknown;
table?: string;
}): void;
/** 广播表变更到其他标签页(多标签页同步) */
broadcastChange(tableName: string): void;
/** 写语句对应的表名(多标签页广播用) */
private writeStatementTable;
private migrations;
/** 注册迁移 */
addMigration(version: number, up: (db: MetonaSqlark) => Promise<void>): void;
/** 执行迁移到指定版本 */
migrateTo(targetVersion: number): Promise<void>;
/** 获取插件管理器 */
getPluginManager(): PluginManager;
/** 注册钩子 */
on(hook: HookName, callback: HookCallback): void;
/** 关闭数据库 */
close(): Promise<void>;
/** 获取底层引擎 */
getEngine(): IStorageEngine;
private createEngine;
private ensureReady;
/** 错误回调分发 */
private _onError;
/** 调试日志 */
private _debug;
}
/**
* metona-sqlark Memory Engine — 基于 Map 的内存存储引擎
* @module engine/memory
*/
declare class MemoryEngine implements IStorageEngine {
readonly name = "memory";
private tables;
private schemas;
private indexes;
private opened;
private snapshot;
open(_dbName: string, _version: number): Promise<void>;
close(): Promise<void>;
isOpen(): boolean;
createTable(schema: TableSchema): Promise<void>;
dropTable(tableName: string): Promise<void>;
hasTable(tableName: string): Promise<boolean>;
getTableNames(): Promise<string[]>;
getTableSchema(tableName: string): Promise<TableSchema | null>;
insert(tableName: string, rows: Record<string, unknown>[]): Promise<string[]>;
find(tableName: string, query: QueryPlan): Promise<Record<string, unknown>[]>;
/** v0.4.0: 流式查询 — 逐行回调(单次迭代,不物化结果数组) */
findStream(tableName: string, query: QueryPlan, onRow: (row: Record<string, unknown>) => void): Promise<number>;
update(tableName: string, query: QueryPlan, updates: Record<string, unknown>): Promise<number>;
delete(tableName: string, query: QueryPlan): Promise<number>;
count(tableName: string, query?: QueryPlan): Promise<number>;
clear(tableName: string): Promise<void>;
createIndex(tableName: string, column: string, unique?: boolean): Promise<void>;
dropIndex(tableName: string, column: string, _indexName?: string): Promise<void>;
beginTransaction(): Promise<void>;
commitTransaction(): Promise<void>;
rollbackTransaction(): Promise<void>;
private deepCloneMapMap;
private deepCloneIndexes;
private ensureTable;
private getPrimaryKey;
private validateRow;
private checkType;
/** O(1) 唯一性检查:利用哈希索引 */
private checkUniqueness;
/** 索引查找 */
private tryIndexLookup;
/** 更新索引 */
private updateIndexes;
/** v0.3.3: 从所有索引中移除一行的条目(update/delete 前调用,修复索引过期/残留) */
private removeIndexEntries;
/**
* 级联删除:查找引用 tableName.pkValue 的所有表的行并删除。
* @returns 级联删除的行数
*/
private cascadeDelete;
}
/**
* metona-sqlark IndexedDB Engine — 基于 IndexedDB 的持久化存储引擎
* @module engine/indexeddb
*
* v0.1.13: 支持事务 — beginTransaction 延迟 IDB 写入,commit 批量刷盘,rollback 恢复快照。
*/
declare class IndexedDBEngine implements IStorageEngine {
readonly name = "indexeddb";
private db;
private dbName;
private version;
private memoryCache;
private txActive;
open(dbName: string, version: number): Promise<void>;
/**
* 从 IDB 恢复内存 schema
* 1. 优先读取持久化的 schema 记录('__metona_schema' storev0.3.2
* 2. 旧数据回退:从 objectStore 主键 / 索引 / 样例数据推断
*/
private rebuildSchemaFromIDB;
close(): Promise<void>;
isOpen(): boolean;
createTable(schema: TableSchema): Promise<void>;
dropTable(tableName: string): Promise<void>;
hasTable(tableName: string): Promise<boolean>;
getTableNames(): Promise<string[]>;
getTableSchema(tableName: string): Promise<TableSchema | null>;
insert(tableName: string, rows: Record<string, unknown>[]): Promise<string[]>;
find(tableName: string, query: QueryPlan): Promise<Record<string, unknown>[]>;
/** v0.4.0: 流式查询 — IDB 批量读入后逐行回调(保持接口一致性) */
findStream(tableName: string, query: QueryPlan, onRow: (row: Record<string, unknown>) => void): Promise<number>;
update(tableName: string, query: QueryPlan, updates: Record<string, unknown>): Promise<number>;
delete(tableName: string, query: QueryPlan): Promise<number>;
count(tableName: string, query?: QueryPlan): Promise<number>;
clear(tableName: string): Promise<void>;
createIndex(tableName: string, column: string, unique?: boolean): Promise<void>;
dropIndex(tableName: string, column: string, _indexName?: string): Promise<void>;
beginTransaction(): Promise<void>;
commitTransaction(): Promise<void>;
rollbackTransaction(): Promise<void>;
private idbCreateTable;
private idbDropTable;
private idbInsert;
private idbFind;
/** 尝试使用 IDB 索引进行等值查询,成功返回结果,不适用返回 null */
private tryIDBIndexLookup;
private idbUpdate;
private idbDelete;
private idbClear;
/** 将内存缓存中的所有表数据原子性刷新到 IndexedDB */
private flushToIDB;
private ensureDB;
}
/**
* metona-sqlark OPFS Engine — 基于 Origin Private File System 的持久化存储引擎
* @module engine/opfs
*
* 使用 JSON-per-table 文件存储方案。
* 目录结构:{dbName}/tables/{tableName}.json
*/
declare class OPFSEngine implements IStorageEngine {
readonly name = "opfs";
private root;
private tablesDir;
private dbName;
private memoryCache;
open(dbName: string, version: number): Promise<void>;
close(): Promise<void>;
isOpen(): boolean;
createTable(schema: TableSchema): Promise<void>;
dropTable(tableName: string): Promise<void>;
hasTable(tableName: string): Promise<boolean>;
getTableNames(): Promise<string[]>;
getTableSchema(tableName: string): Promise<TableSchema | null>;
insert(tableName: string, rows: Record<string, unknown>[]): Promise<string[]>;
find(tableName: string, query: QueryPlan): Promise<Record<string, unknown>[]>;
/** v0.4.0: 流式查询(委托内存缓存) */
findStream(tableName: string, query: QueryPlan, onRow: (row: Record<string, unknown>) => void): Promise<number>;
update(tableName: string, query: QueryPlan, updates: Record<string, unknown>): Promise<number>;
delete(tableName: string, query: QueryPlan): Promise<number>;
count(tableName: string, query?: QueryPlan): Promise<number>;
clear(tableName: string): Promise<void>;
createIndex(tableName: string, column: string, unique?: boolean): Promise<void>;
dropIndex(tableName: string, column: string, indexName?: string): Promise<void>;
beginTransaction(): Promise<void>;
commitTransaction(): Promise<void>;
rollbackTransaction(): Promise<void>;
private ensureDir;
private writeTableData;
private readTableData;
/** 从 OPFS 加载已有表数据到内存缓存 */
private loadExistingTables;
/** 从 OPFS 加载表数据到内存缓存 */
loadTableIntoMemory(tableName: string, schema: TableSchema): Promise<void>;
}
interface AriaEngineConfig {
/** 页面大小(默认 4096 */
pageSize?: number;
/** Buffer Pool 页面数量(默认 256 */
bufferPoolPages?: number;
/** MemTable 刷盘阈值(默认 4MB */
memtableSizeThreshold?: number;
/** LSM 层级之间的容量倍数(默认 10) */
levelSizeMultiplier?: number;
/** Bloom Filter 每 key 位数(默认 10 */
bloomFilterBitsPerKey?: number;
/** 是否启用 WAL(默认 true */
walEnabled?: boolean;
/** WAL 同步模式 */
walSyncMode?: 'full' | 'batch' | 'none';
/** Checkpoint 间隔(操作数,默认 1000 */
checkpointInterval?: number;
/** 是否启用页面压缩(默认 false) */
compression?: boolean;
/** 存储后端 */
storageBackend?: 'indexeddb' | 'opfs' | 'memory';
/** WAL 大小阈值(字节,超过则强制 checkpoint,默认 16MB */
walSizeThreshold?: number;
/** 最大内存预算(MB,默认 64) */
maxMemoryMB?: number;
}
declare class AriaEngine implements IStorageEngine {
readonly name = "aria";
private config;
private lsm;
private wal;
private checkpointManager;
private backend;
private opened;
private dbName;
private schemas;
private tablePKs;
private opCounter;
private secondaryIndexes;
private mvcc;
private currentTxnId;
private txnSnapshot;
private gcCounter;
private bufferPool;
constructor(config?: AriaEngineConfig);
open(dbName: string, _version: number): Promise<void>;
close(): Promise<void>;
/**
* v0.4.1: 重置数据库 — 清空全部数据与表结构(演示页刷新/重新初始化用)。
* 清空存储后端、LSM、WAL、MVCC 与二级索引,后续可继续使用本实例。
*/
clearAll(): Promise<void>;
isOpen(): boolean;
createTable(schema: TableSchema): Promise<void>;
dropTable(tableName: string): Promise<void>;
hasTable(tableName: string): Promise<boolean>;
getTableNames(): Promise<string[]>;
getTableSchema(tableName: string): Promise<TableSchema | null>;
insert(tableName: string, rows: Record<string, unknown>[]): Promise<string[]>;
find(tableName: string, query: QueryPlan): Promise<Record<string, unknown>[]>;
update(tableName: string, query: QueryPlan, updates: Record<string, unknown>): Promise<number>;
delete(tableName: string, query: QueryPlan): Promise<number>;
/**
* v0.4.1: 外键级联规则 — 对齐 MemoryEngine.cascadeDelete 行为。
* 删除 tableName 主键为 pkValue 的行前,检查引用它的所有表:
* - RESTRICT: 存在引用行 → 抛 FOREIGN_KEY_VIOLATION
* - CASCADE: 递归删除引用行(含索引/WAL)
* - SET NULL: 引用行外键列置 null(含索引/WAL)
* @returns 级联影响的行数(CASCADE 删除行数 + SET NULL 更新行数)
*/
private applyForeignKeyRules;
/**
* v0.4.0: 流式查询 — 逐行回调,不物化结果数组。
* 全表路径走 LSM rangeScanLazy 惰性扫描;索引等值/范围路径复用 tryIndexLookup。
* 事务中回退物化(快照合并需要全量行集)。
*/
findStream(tableName: string, query: QueryPlan, onRow: (row: Record<string, unknown>) => void): Promise<number>;
count(tableName: string, query?: QueryPlan): Promise<number>;
clear(tableName: string): Promise<void>;
/**
* v0.4.1: ALTER TABLE — 结构变更真正生效于存储:
* - ADD: 持久化 schemapersistSchemas),行无需修改
* - DROP: 持久化 schema + 遍历主 LSM 重写所有行(移除该列键)+ WAL UPDATE 记录
* (通用路径 getTableSchema 返回副本,Executor 的引用修改对 Aria 无效)
*/
alterTable(tableName: string, action: 'ADD' | 'DROP', column: ColumnDef & {
name: string;
}): Promise<void>;
createIndex(tableName: string, column: string, unique?: boolean): Promise<void>;
dropIndex(tableName: string, column: string, _indexName?: string): Promise<void>;
beginTransaction(): Promise<void>;
commitTransaction(): Promise<void>;
rollbackTransaction(): Promise<void>;
private savepoints;
savepoint(name: string): Promise<void>;
rollbackToSavepoint(name: string): Promise<void>;
releaseSavepoint(name: string): Promise<void>;
backup(): Promise<Record<string, Record<string, unknown>[]>>;
private getAllRows;
/**
* v0.3.3: 将事务未提交快照的变更合并到行列表(新增/更新/删除标记)。
* 幂等操作:行已是最新时不重复修改。
*/
private mergeTxnSnapshot;
private getPK;
private validateRow;
private checkType;
private persistSchemas;
private loadSchemas;
/**
* 创建命名空间隔离的 SSTableStore。
*
* 主 LSM 与每个二级索引 LSM 各持有独立实例:
* - 文件 key 前缀隔离(sst_ / sst_idx_${table}_${col}_
* - 元数据 key 隔离(__aria_lsm_meta / __aria_lsm_meta_${ns}
* - id 序列独立(避免 v0.2.4 共享 id 空间导致的文件互相覆盖)
*/
private createSSTableStore;
private applyWALRecord;
/**
* v0.3.3: DROP_TABLE 恢复 — 删除 schema 并清除主 LSM 中该表的所有残留数据。
*
* 此前 DROP_TABLE 在恢复时被忽略,而 CREATE_TABLE 回放会重建 schema
* 导致崩溃后"已删除的表和数据复活"(实证 P0 bug)。
*/
private applyDropTableRecovery;
/** 更新行的二级索引条目 */
private updateSecondaryIndexes;
/** 通过二级索引快速查找 */
private tryIndexLookup;
/** 从索引扫描结果恢复完整行 */
private indexScanToRows;
/** 每 10 次 gc 计数器触发一次 MVCC 垃圾回收 */
private tryGC;
/** 回收主 LSM 与所有二级索引 LSM 的临时缓存超限 */
private trimAllCaches;
/** 检查内存预算,超出时强制 flush + GC */
private checkMemoryBudget;
/** 估算 WAL 大小(字节) */
getWALEstimatedSize(): number;
/**
* ANALYZE: 收集表统计信息
* 返回行数、平均行大小、索引深度等
*/
analyzeTable(tableName: string): Promise<Record<string, unknown>>;
/**
* REINDEX: 重建指定表的所有二级索引
*/
reindexTable(tableName: string): Promise<number>;
/**
* VACUUM: 压缩 LSM + 清理碎片
*/
vacuum(): Promise<{
compactedLevels: number;
gcVersions: number;
}>;
/**
* 查询优化器:估算各索引成本,选择最优方案
*/
estimateQueryCost(tableName: string, query: QueryPlan): {
strategy: string;
estimatedRows: number;
};
private ensureOpen;
private ensureTable;
/** Get the number of WAL records stored */
private getWALCount;
/** Set the number of WAL records stored */
private setWALCount;
}
/**
* metona-sqlark Hybrid Engine — 内存 + 磁盘混合存储引擎
* @module hybrid/index
*
* 采用 write-through 策略:
* - 所有写操作同时写入内存和磁盘
* - 所有读操作直接从内存返回
* - 数据库打开时从磁盘加载数据到内存
*/
declare class HybridEngine implements IStorageEngine {
readonly name = "hybrid";
private memoryEngine;
private diskEngine;
private diskEngineType;
private dbName;
private version;
constructor(diskEngine?: DiskEngine);
open(dbName: string, version: number): Promise<void>;
/**
* 从磁盘重载内存缓存(v0.3.2:多标签页同步)。
* 其他标签页写入磁盘后调用,使本标签页读到最新数据。
*/
reloadMemoryFromDisk(): Promise<void>;
close(): Promise<void>;
isOpen(): boolean;
createTable(schema: TableSchema): Promise<void>;
dropTable(tableName: string): Promise<void>;
hasTable(tableName: string): Promise<boolean>;
getTableNames(): Promise<string[]>;
getTableSchema(tableName: string): Promise<TableSchema | null>;
insert(tableName: string, rows: Record<string, unknown>[]): Promise<string[]>;
find(tableName: string, query: QueryPlan): Promise<Record<string, unknown>[]>;
/** v0.4.0: 流式查询(内存引擎逐行回调) */
findStream(tableName: string, query: QueryPlan, onRow: (row: Record<string, unknown>) => void): Promise<number>;
update(tableName: string, query: QueryPlan, updates: Record<string, unknown>): Promise<number>;
delete(tableName: string, query: QueryPlan): Promise<number>;
count(tableName: string, query?: QueryPlan): Promise<number>;
clear(tableName: string): Promise<void>;
createIndex(tableName: string, column: string, unique?: boolean): Promise<void>;
dropIndex(tableName: string, column: string, indexName?: string): Promise<void>;
beginTransaction(): Promise<void>;
commitTransaction(): Promise<void>;
rollbackTransaction(): Promise<void>;
/** 获取磁盘引擎类型 */
getDiskEngineType(): DiskEngine;
/** 获取内存引擎(供内部使用) */
getMemoryEngine(): MemoryEngine;
}
/**
* metona-sqlark SQL Parser — 递归下降语法分析器
* @module sql/parser
*
* Token 流 → AST Statement。
* 支持的语法是标准 SQL 的子集。
*/
/** 解析 SQL 字符串为 AST Statement */
declare function parse(sql: string): Statement;
/** 解析 SQL 字符串为 AST Statement 数组(分号分隔的多语句支持,v0.3.0) */
declare function parseAll(sql: string): Statement[];
/**
* metona-sqlark SQL Token Types — 词法单元定义
* @module sql/tokens
*/
declare enum TokenType {
SELECT = "SELECT",
FROM = "FROM",
WHERE = "WHERE",
INSERT = "INSERT",
INTO = "INTO",
VALUES = "VALUES",
UPDATE = "UPDATE",
SET = "SET",
DELETE = "DELETE",
CREATE = "CREATE",
TABLE = "TABLE",
DROP = "DROP",
ORDER = "ORDER",
BY = "BY",
ASC = "ASC",
DESC = "DESC",
LIMIT = "LIMIT",
OFFSET = "OFFSET",
AND = "AND",
OR = "OR",
NOT = "NOT",
LIKE = "LIKE",
IN = "IN",
PRIMARY = "PRIMARY",
KEY = "KEY",
UNIQUE = "UNIQUE",
DEFAULT = "DEFAULT",
NULL = "NULL",
TRUE = "TRUE",
REFERENCES = "REFERENCES",
CASCADE = "CASCADE",
BETWEEN = "BETWEEN",
IF = "IF",
EXISTS = "EXISTS",
FALSE = "FALSE",
ALTER = "ALTER",
ADD = "ADD",
TRUNCATE = "TRUNCATE",
INNER = "INNER",
LEFT = "LEFT",
RIGHT = "RIGHT",
CROSS = "CROSS",
JOIN = "JOIN",
ON = "ON",
AS = "AS",
OUTER = "OUTER",
GROUP = "GROUP",
HAVING = "HAVING",
COUNT = "COUNT",
SUM = "SUM",
AVG = "AVG",
MIN = "MIN",
MAX = "MAX",
DISTINCT = "DISTINCT",
BEGIN = "BEGIN",
COMMIT = "COMMIT",
ROLLBACK = "ROLLBACK",
UNION = "UNION",
ALL = "ALL",
INDEX = "INDEX",
CASE = "CASE",
WHEN = "WHEN",
THEN = "THEN",
ELSE = "ELSE",
END = "END",
IDENTIFIER = "IDENTIFIER",
STRING = "STRING",
NUMBER = "NUMBER",
COMMA = "COMMA",
LPAREN = "LPAREN",
RPAREN = "RPAREN",
SEMICOLON = "SEMICOLON",
EQ = "EQ",
NEQ = "NEQ",
GT = "GT",
GTE = "GTE",
LT = "LT",
LTE = "LTE",
STAR = "STAR",
DOT = "DOT",
EOF = "EOF",
ILLEGAL = "ILLEGAL"
}
interface Token {
type: TokenType;
value: string;
position: number;
}
/**
* metona-sqlark SQL Lexer — 词法分析器
* @module sql/lexer
*
* 将 SQL 字符串切分为 Token 流。
*/
/** 将 SQL 字符串解析为 Token 列表 */
declare function tokenize(sql: string): Token[];
/**
* AriaEngine Storage Backend — 存储后端抽象层
* @module engine/aria/store/backend
*
* 封装底层浏览器存储 APIIndexedDB / OPFS / Memory 回退),
* 供 Buffer Pool 的 PageIO 和 WAL 的 WALStore 使用。
*/
interface IStorageBackend {
/** 打开存储 */
open(name: string): Promise<void>;
/** 关闭存储 */
close(): Promise<void>;
/** 是否已打开 */
isOpen(): boolean;
/** 读取数据块 */
read(key: string): Promise<ArrayBuffer | null>;
/** 写入数据块 */
write(key: string, data: ArrayBuffer): Promise<void>;
/** 删除数据块 */
delete(key: string): Promise<void>;
/** 列出所有 key */
listKeys(): Promise<string[]>;
/** 检查 key 是否存在 */
exists(key: string): Promise<boolean>;
/** 清空所有数据 */
clear(): Promise<void>;
}
/**
* AriaEngine OPFS Backend — 基于 Origin Private File System 的自研存储后端
* @module engine/aria/store/opfs_backend
*
* 零外部依赖,纯浏览器文件系统 API。
* 每个 key 对应 OPFS 目录下的一个二进制文件。
*
* 浏览器要求:Chrome 102+ / Edge 102+
*/
declare class OPFSBackend implements IStorageBackend {
private root;
private dbDir;
private dbName;
private writeQueue;
open(name: string): Promise<void>;
close(): Promise<void>;
isOpen(): boolean;
read(key: string): Promise<ArrayBuffer | null>;
write(key: string, data: ArrayBuffer): Promise<void>;
delete(key: string): Promise<void>;
listKeys(): Promise<string[]>;
exists(key: string): Promise<boolean>;
clear(): Promise<void>;
}
/**
* metona-sqlark — 入口文件
* @module metona-sqlark
* @version 0.4.1
*
* 前端关系型数据库,内存与磁盘双模式。
* 支持 Query Builder 链式 API 和 SQL 字符串查询。
*/
/**
* 创建数据库实例并初始化
*
* @example
* ```ts
* const db = await MetonaSqlark.create({
* name: 'my-app',
* mode: 'hybrid',
* });
*
* await db.defineTable('users', {
* id: { type: 'string', primaryKey: true },
* name: { type: 'string', required: true },
* });
*
* await db.table('users').insert({ id: '1', name: 'Alice' });
* const results = await db.query('SELECT * FROM users');
* ```
*/
declare function create(config: DatabaseConfig): Promise<MetonaSqlark>;
declare const api: {
VERSION: string;
version: string;
create: typeof create;
MetonaSqlark: typeof MetonaSqlark;
MeSqlark: typeof MetonaSqlark;
};
declare global {
interface Window {
MetonaSqlark: typeof api;
MeSqlark: typeof api;
}
}
declare const MeSqlark: typeof MetonaSqlark;
export { AriaEngine, AriaEngineConfig, ColumnDef, DatabaseConfig, DeleteStatement, DiskEngine, FieldType, HybridEngine, IStorageEngine, IndexedDBEngine, InsertStatement, MeSqlark, MemoryEngine, MetonaSqlark, OPFSBackend, OPFSEngine, SelectStatement, Statement, StorageMode, Table, TableSchema, UpdateStatement, VERSION, api, create, api as default, parse, parseAll, tokenize };