feat: SQL 语法支持 BETWEEN AND、DROP TABLE IF EXISTS
CI / test (18.x) (push) Waiting to run
CI / test (20.x) (push) Waiting to run
CI / test (22.x) (push) Waiting to run
CI / test (24.x) (push) Waiting to run

This commit is contained in:
thzxx
2026-07-26 17:55:45 +08:00
parent 287f2a2b22
commit 1f8e11bf72
14 changed files with 181 additions and 13 deletions
+2
View File
@@ -103,6 +103,8 @@ export interface CreateTableStatement {
export interface DropTableStatement {
type: 'DROP_TABLE';
name: string;
/** IF EXISTS — 表不存在时不报错 */
ifExists?: boolean;
}
// ---------------------------------------------------------------------------
+4
View File
@@ -234,6 +234,10 @@ export class QueryExecutor {
}
private async executeDropTable(stmt: DropTableStatement): Promise<void> {
if (stmt.ifExists) {
const exists = await this.engine.hasTable(stmt.name);
if (!exists) return; // IF EXISTS: 表不存在时静默返回
}
return this.engine.dropTable(stmt.name);
}
+31 -1
View File
@@ -423,8 +423,15 @@ export class Parser {
private parseDropTable(): DropTableStatement {
this.expect(TokenType.DROP);
this.expect(TokenType.TABLE);
// IF EXISTS(可选)
let ifExists = false;
if (this.curTokenIs(TokenType.IF)) {
this.nextToken();
this.expect(TokenType.EXISTS);
ifExists = true;
}
const tableName = this.expectIdentifier('table name');
return { type: 'DROP_TABLE', name: tableName };
return { type: 'DROP_TABLE', name: tableName, ifExists: ifExists || undefined };
}
// ===================================================================
@@ -483,6 +490,29 @@ export class Parser {
return result;
}
// BETWEEN val1 AND val2
if (this.curTokenIs(TokenType.BETWEEN)) {
this.nextToken();
const low = this.parseValue();
this.expect(TokenType.AND);
const high = this.parseValue();
const result: WhereCondition = {};
result[column] = { $gte: low, $lte: high };
return result;
}
// NOT BETWEEN val1 AND val2
if (this.curTokenIs(TokenType.NOT) && this.peekTokenIs(TokenType.BETWEEN)) {
this.nextToken(); // skip NOT
this.nextToken(); // skip BETWEEN
const low = this.parseValue();
this.expect(TokenType.AND);
const high = this.parseValue();
const result: WhereCondition = {};
result[column] = { $not: { $gte: low, $lte: high } };
return result;
}
// NOT LIKE / NOT INNOT 后紧跟 LIKE 或 IN
if (this.curTokenIs(TokenType.NOT)) {
if (this.peekTokenIs(TokenType.IN)) {
+6
View File
@@ -40,6 +40,9 @@ export enum TokenType {
TRUE = 'TRUE',
REFERENCES = 'REFERENCES',
CASCADE = 'CASCADE',
BETWEEN = 'BETWEEN',
IF = 'IF',
EXISTS = 'EXISTS',
FALSE = 'FALSE',
// JOIN 相关
@@ -133,6 +136,9 @@ export const KEYWORDS: Record<string, TokenType> = {
'FALSE': TokenType.FALSE,
'REFERENCES': TokenType.REFERENCES,
'CASCADE': TokenType.CASCADE,
'BETWEEN': TokenType.BETWEEN,
'IF': TokenType.IF,
'EXISTS': TokenType.EXISTS,
// JOIN
'INNER': TokenType.INNER,