feat: metona-sqlark v0.1.12 — 前端TypeScript关系型数据库
- 4种存储引擎:Memory / IndexedDB / OPFS / Hybrid - 完整SQL支持:SELECT/INSERT/UPDATE/DELETE/JOIN/GROUP BY/HAVING/DISTINCT - Query Builder链式API + TypeScript泛型支持 - 聚合函数:COUNT/SUM/AVG/MIN/MAX - 事务、插件系统(14 hooks)、发布订阅、数据迁移、导入导出 - React/Vue框架集成 - 264个测试用例,93.46%覆盖率 - 零运行时依赖
This commit is contained in:
@@ -0,0 +1,182 @@
|
||||
/**
|
||||
* metona-sqlark Query Builder — 链式查询构建器
|
||||
* @module query/builder
|
||||
*
|
||||
* 链式调用 → 构建 AST → 执行引擎操作。
|
||||
* 支持 JOIN(需要 Executor)。
|
||||
*/
|
||||
|
||||
import type { IStorageEngine } from '../engine/interface';
|
||||
import type { WhereCondition, OrderBy, SortDirection } from '../constants';
|
||||
import type { SelectStatement, UpdateStatement, DeleteStatement, JoinType, JoinClause } from './ast';
|
||||
import { QueryExecutor } from './executor';
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SelectQueryBuilder
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export class SelectQueryBuilder {
|
||||
private _where: WhereCondition = {};
|
||||
private _orderBy: OrderBy[] = [];
|
||||
private _limit?: number;
|
||||
private _offset?: number;
|
||||
private _joins: JoinClause[] = [];
|
||||
private _alias?: string;
|
||||
private _executor?: QueryExecutor;
|
||||
|
||||
constructor(
|
||||
private engine: IStorageEngine,
|
||||
private tableName: string,
|
||||
private _columns: string[] = ['*'],
|
||||
executor?: QueryExecutor,
|
||||
) {
|
||||
this._executor = executor;
|
||||
}
|
||||
|
||||
/** 主表别名 */
|
||||
as(alias: string): this {
|
||||
this._alias = alias;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** INNER JOIN */
|
||||
innerJoin(table: string, on: WhereCondition, alias?: string): this {
|
||||
return this._addJoin('INNER', table, on, alias);
|
||||
}
|
||||
|
||||
/** LEFT JOIN */
|
||||
leftJoin(table: string, on: WhereCondition, alias?: string): this {
|
||||
return this._addJoin('LEFT', table, on, alias);
|
||||
}
|
||||
|
||||
/** RIGHT JOIN */
|
||||
rightJoin(table: string, on: WhereCondition, alias?: string): this {
|
||||
return this._addJoin('RIGHT', table, on, alias);
|
||||
}
|
||||
|
||||
/** CROSS JOIN */
|
||||
crossJoin(table: string, alias?: string): this {
|
||||
return this._addJoin('CROSS', table, {}, alias);
|
||||
}
|
||||
|
||||
/** 通用 JOIN */
|
||||
join(table: string, on: WhereCondition, alias?: string): this {
|
||||
return this._addJoin('INNER', table, on, alias);
|
||||
}
|
||||
|
||||
private _addJoin(type: JoinType, table: string, on: WhereCondition, alias?: string): this {
|
||||
this._joins.push({ type, table, on, alias });
|
||||
return this;
|
||||
}
|
||||
|
||||
/** 添加过滤条件 */
|
||||
where(condition: WhereCondition): this {
|
||||
this._where = { ...this._where, ...condition };
|
||||
return this;
|
||||
}
|
||||
|
||||
/** 排序 */
|
||||
orderBy(column: string, direction: SortDirection = 'asc'): this {
|
||||
this._orderBy.push({ column, direction });
|
||||
return this;
|
||||
}
|
||||
|
||||
/** 限制返回条数 */
|
||||
limit(n: number): this {
|
||||
this._limit = n;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** 偏移量 */
|
||||
offset(n: number): this {
|
||||
this._offset = n;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** 执行查询 */
|
||||
async execute(): Promise<Record<string, unknown>[]> {
|
||||
// 有 JOIN → 通过 Executor 执行
|
||||
if (this._joins.length > 0 && this._executor) {
|
||||
const ast = this.toAST();
|
||||
return this._executor.execute(ast) as Promise<Record<string, unknown>[]>;
|
||||
}
|
||||
|
||||
// 无 JOIN → 直接调用引擎
|
||||
return this.engine.find(this.tableName, {
|
||||
table: this.tableName,
|
||||
columns: this._columns,
|
||||
where: this._where,
|
||||
orderBy: this._orderBy.length > 0 ? this._orderBy : undefined,
|
||||
limit: this._limit,
|
||||
offset: this._offset,
|
||||
});
|
||||
}
|
||||
|
||||
/** 获取 AST */
|
||||
toAST(): SelectStatement {
|
||||
return {
|
||||
type: 'SELECT',
|
||||
columns: this._columns,
|
||||
from: this.tableName,
|
||||
alias: this._alias,
|
||||
joins: this._joins.length > 0 ? [...this._joins] : undefined,
|
||||
where: this._where,
|
||||
orderBy: this._orderBy.length > 0 ? this._orderBy : undefined,
|
||||
limit: this._limit,
|
||||
offset: this._offset,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// UpdateQueryBuilder
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export class UpdateQueryBuilder {
|
||||
private _where: WhereCondition = {};
|
||||
|
||||
constructor(
|
||||
private engine: IStorageEngine,
|
||||
private tableName: string,
|
||||
private _updates: Record<string, unknown>,
|
||||
) {}
|
||||
|
||||
where(condition: WhereCondition): this {
|
||||
this._where = { ...this._where, ...condition };
|
||||
return this;
|
||||
}
|
||||
|
||||
async execute(): Promise<number> {
|
||||
return this.engine.update(this.tableName, { table: this.tableName, where: this._where }, this._updates);
|
||||
}
|
||||
|
||||
toAST(): UpdateStatement {
|
||||
return { type: 'UPDATE', table: this.tableName, sets: this._updates, where: this._where };
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// DeleteQueryBuilder
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export class DeleteQueryBuilder {
|
||||
private _where: WhereCondition = {};
|
||||
|
||||
constructor(
|
||||
private engine: IStorageEngine,
|
||||
private tableName: string,
|
||||
) {}
|
||||
|
||||
where(condition: WhereCondition): this {
|
||||
this._where = { ...this._where, ...condition };
|
||||
return this;
|
||||
}
|
||||
|
||||
async execute(): Promise<number> {
|
||||
return this.engine.delete(this.tableName, { table: this.tableName, where: this._where });
|
||||
}
|
||||
|
||||
toAST(): DeleteStatement {
|
||||
return { type: 'DELETE', from: this.tableName, where: this._where };
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user