release: v0.2.5 — 质量加固 + Bug修复 + 性能优化 + SQL扩展
This commit is contained in:
+26
-2
@@ -19,7 +19,9 @@ export type StatementType =
|
||||
| 'UPDATE'
|
||||
| 'DELETE'
|
||||
| 'CREATE_TABLE'
|
||||
| 'DROP_TABLE';
|
||||
| 'DROP_TABLE'
|
||||
| 'ALTER_TABLE'
|
||||
| 'TRUNCATE_TABLE';
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// 列引用
|
||||
@@ -171,6 +173,26 @@ export interface SelectStatement {
|
||||
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 联合类型
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -182,4 +204,6 @@ export type Statement =
|
||||
| UpdateStatement
|
||||
| DeleteStatement
|
||||
| CreateTableStatement
|
||||
| DropTableStatement;
|
||||
| DropTableStatement
|
||||
| AlterTableStatement
|
||||
| TruncateTableStatement;
|
||||
|
||||
+47
-1
@@ -9,6 +9,7 @@ import type { IStorageEngine } from '../engine/interface';
|
||||
import type {
|
||||
Statement, SelectStatement, InsertStatement, UpdateStatement,
|
||||
DeleteStatement, CreateTableStatement, DropTableStatement, JoinClause,
|
||||
AlterTableStatement, TruncateTableStatement,
|
||||
} from './ast';
|
||||
import { DatabaseError } from '../constants';
|
||||
import { compileStatement } from './compiler';
|
||||
@@ -21,7 +22,16 @@ import type { WhereCondition } from '../constants';
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export class QueryExecutor {
|
||||
constructor(private engine: IStorageEngine) {}
|
||||
private maxRowsPerQuery: number;
|
||||
|
||||
constructor(private engine: IStorageEngine, maxRowsPerQuery: number = 0) {
|
||||
this.maxRowsPerQuery = maxRowsPerQuery;
|
||||
}
|
||||
|
||||
/** 设置查询结果行数上限 */
|
||||
setMaxRowsPerQuery(max: number): void {
|
||||
this.maxRowsPerQuery = max;
|
||||
}
|
||||
|
||||
async execute(stmt: Statement): Promise<unknown> {
|
||||
switch (stmt.type) {
|
||||
@@ -32,6 +42,8 @@ export class QueryExecutor {
|
||||
case 'DELETE': return this.executeDelete(stmt);
|
||||
case 'CREATE_TABLE': return this.executeCreateTable(stmt);
|
||||
case 'DROP_TABLE': return this.executeDropTable(stmt);
|
||||
case 'ALTER_TABLE': return this.executeAlterTable(stmt as any);
|
||||
case 'TRUNCATE_TABLE': return this.executeTruncateTable(stmt as any);
|
||||
default: throw new DatabaseError('Unknown statement type', 'UNKNOWN_STATEMENT');
|
||||
}
|
||||
}
|
||||
@@ -99,6 +111,12 @@ export class QueryExecutor {
|
||||
if (!hasGroupBy && !hasAggregate && stmt.columns.length > 0 && stmt.columns[0] !== '*') {
|
||||
rows = rows.map((row) => projectColumns(row, stmt.columns));
|
||||
}
|
||||
|
||||
// 全局行数上限保护
|
||||
if (this.maxRowsPerQuery > 0 && rows.length > this.maxRowsPerQuery) {
|
||||
rows = rows.slice(0, this.maxRowsPerQuery);
|
||||
}
|
||||
|
||||
return rows;
|
||||
}
|
||||
|
||||
@@ -272,6 +290,34 @@ export class QueryExecutor {
|
||||
return this.engine.dropTable(stmt.name);
|
||||
}
|
||||
|
||||
private async executeAlterTable(stmt: AlterTableStatement): Promise<void> {
|
||||
const exists = await this.engine.hasTable(stmt.name);
|
||||
if (!exists) throw new DatabaseError(`Table "${stmt.name}" does not exist`, 'TABLE_NOT_FOUND');
|
||||
const schema = await this.engine.getTableSchema(stmt.name);
|
||||
if (!schema) return;
|
||||
|
||||
if (stmt.action === 'ADD') {
|
||||
if (schema.columns[stmt.column.name]) {
|
||||
throw new DatabaseError(`Column "${stmt.column.name}" already exists in table "${stmt.name}"`, 'COLUMN_EXISTS');
|
||||
}
|
||||
schema.columns[stmt.column.name] = astColumnToColumnDef(stmt.column);
|
||||
} else if (stmt.action === 'DROP') {
|
||||
if (!schema.columns[stmt.column.name]) {
|
||||
throw new DatabaseError(`Column "${stmt.column.name}" does not exist in table "${stmt.name}"`, 'COLUMN_NOT_FOUND');
|
||||
}
|
||||
delete schema.columns[stmt.column.name];
|
||||
}
|
||||
// 重建表结构
|
||||
await this.engine.dropTable(stmt.name);
|
||||
await this.engine.createTable(schema);
|
||||
}
|
||||
|
||||
private async executeTruncateTable(stmt: TruncateTableStatement): Promise<void> {
|
||||
const exists = await this.engine.hasTable(stmt.name);
|
||||
if (!exists) throw new DatabaseError(`Table "${stmt.name}" does not exist`, 'TABLE_NOT_FOUND');
|
||||
return this.engine.clear(stmt.name);
|
||||
}
|
||||
|
||||
getEngine(): IStorageEngine { return this.engine; }
|
||||
|
||||
// ===================================================================
|
||||
|
||||
Reference in New Issue
Block a user