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
+40 -1
View File
@@ -1614,6 +1614,11 @@ class QueryExecutor {
return this.engine.createTable(createSchema(stmt.name, columns));
}
async executeDropTable(stmt) {
if (stmt.ifExists) {
const exists = await this.engine.hasTable(stmt.name);
if (!exists)
return; // IF EXISTS: 表不存在时静默返回
}
return this.engine.dropTable(stmt.name);
}
getEngine() { return this.engine; }
@@ -1766,6 +1771,9 @@ var TokenType;
TokenType["TRUE"] = "TRUE";
TokenType["REFERENCES"] = "REFERENCES";
TokenType["CASCADE"] = "CASCADE";
TokenType["BETWEEN"] = "BETWEEN";
TokenType["IF"] = "IF";
TokenType["EXISTS"] = "EXISTS";
TokenType["FALSE"] = "FALSE";
// JOIN 相关
TokenType["INNER"] = "INNER";
@@ -1842,6 +1850,9 @@ const KEYWORDS = {
'FALSE': TokenType.FALSE,
'REFERENCES': TokenType.REFERENCES,
'CASCADE': TokenType.CASCADE,
'BETWEEN': TokenType.BETWEEN,
'IF': TokenType.IF,
'EXISTS': TokenType.EXISTS,
// JOIN
'INNER': TokenType.INNER,
'LEFT': TokenType.LEFT,
@@ -2451,8 +2462,15 @@ class Parser {
parseDropTable() {
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 };
}
// ===================================================================
// 条件表达式
@@ -2503,6 +2521,27 @@ class Parser {
result[column] = isNot ? { $ne: null } : { $eq: null };
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 = {};
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 = {};
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)) {