feat: v0.1.13 — 事务回滚 + 子查询 + 外键级联 + 连接池
This commit is contained in:
@@ -14,6 +14,7 @@ import { DatabaseError } from '../constants';
|
||||
import { compileStatement } from './compiler';
|
||||
import { createSchema, astColumnToColumnDef } from '../table/schema';
|
||||
import { matchWhere, applyOrderBy, projectColumns } from './where-matcher';
|
||||
import type { WhereCondition } from '../constants';
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Executor
|
||||
@@ -39,6 +40,11 @@ export class QueryExecutor {
|
||||
// ===================================================================
|
||||
|
||||
private async executeSelect(stmt: SelectStatement): Promise<Record<string, unknown>[]> {
|
||||
// 先解析子查询
|
||||
if (stmt.where && Object.keys(stmt.where).length > 0) {
|
||||
stmt.where = await this.resolveSubqueries(stmt.where);
|
||||
}
|
||||
|
||||
const hasGroupBy = !!(stmt.groupBy && stmt.groupBy.length > 0);
|
||||
let rows: Record<string, unknown>[];
|
||||
|
||||
@@ -226,4 +232,99 @@ export class QueryExecutor {
|
||||
}
|
||||
|
||||
getEngine(): IStorageEngine { return this.engine; }
|
||||
|
||||
// ===================================================================
|
||||
// 子查询解析
|
||||
// ===================================================================
|
||||
|
||||
/**
|
||||
* 递归扫描 WHERE 条件,找到 $subquery 标记并执行子查询,
|
||||
* 将结果替换为具体值。
|
||||
*/
|
||||
private async resolveSubqueries(where: WhereCondition): Promise<WhereCondition> {
|
||||
const resolved: WhereCondition = {};
|
||||
|
||||
for (const [key, value] of Object.entries(where)) {
|
||||
// 逻辑组合操作符
|
||||
if (key === '$and' && Array.isArray(value)) {
|
||||
resolved.$and = await Promise.all(
|
||||
(value as WhereCondition[]).map((sub) => this.resolveSubqueries(sub)),
|
||||
);
|
||||
continue;
|
||||
}
|
||||
if (key === '$or' && Array.isArray(value)) {
|
||||
resolved.$or = await Promise.all(
|
||||
(value as WhereCondition[]).map((sub) => this.resolveSubqueries(sub)),
|
||||
);
|
||||
continue;
|
||||
}
|
||||
if (key === '$not' && typeof value === 'object' && value !== null) {
|
||||
resolved.$not = await this.resolveSubqueries(value as WhereCondition);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 字段条件
|
||||
if (typeof value === 'object' && value !== null) {
|
||||
resolved[key] = await this.resolveOperatorSubqueries(value as Record<string, unknown>);
|
||||
} else {
|
||||
resolved[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
return resolved;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析操作符值中嵌套的子查询
|
||||
*/
|
||||
private async resolveOperatorSubqueries(ops: Record<string, unknown>): Promise<Record<string, unknown>> {
|
||||
const resolved: Record<string, unknown> = {};
|
||||
|
||||
for (const [op, operand] of Object.entries(ops)) {
|
||||
// 处理嵌套 $and/$or(在字段级条件中)
|
||||
if (op === '$and' && Array.isArray(operand)) {
|
||||
resolved.$and = await Promise.all(
|
||||
(operand as WhereCondition[]).map((sub) => this.resolveSubqueries(sub)),
|
||||
);
|
||||
continue;
|
||||
}
|
||||
if (op === '$or' && Array.isArray(operand)) {
|
||||
resolved.$or = await Promise.all(
|
||||
(operand as WhereCondition[]).map((sub) => this.resolveSubqueries(sub)),
|
||||
);
|
||||
continue;
|
||||
}
|
||||
if (op === '$not') {
|
||||
resolved.$not = typeof operand === 'object' && operand !== null
|
||||
? await this.resolveOperatorSubqueries(operand as Record<string, unknown>)
|
||||
: operand;
|
||||
continue;
|
||||
}
|
||||
|
||||
// 子查询检测
|
||||
if (typeof operand === 'object' && operand !== null && '$subquery' in (operand as Record<string, unknown>)) {
|
||||
const subStmt = (operand as Record<string, unknown>).$subquery as SelectStatement;
|
||||
const subResult = await this.executeSelect(subStmt);
|
||||
|
||||
if (op === '$in' || op === '$nin') {
|
||||
// IN 子查询 → 提取第一列的值列表
|
||||
const colName = Object.keys(subResult[0] || {})[0];
|
||||
const values = subResult.map((row) => row[colName]);
|
||||
resolved[op] = values;
|
||||
} else {
|
||||
// 标量子查询 → 取第一行第一列
|
||||
if (subResult.length === 0) {
|
||||
resolved[op] = null;
|
||||
} else {
|
||||
const colName = Object.keys(subResult[0])[0];
|
||||
resolved[op] = subResult[0][colName];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
resolved[op] = operand;
|
||||
}
|
||||
}
|
||||
|
||||
return resolved;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user