feat: SQL 语法支持 BETWEEN AND、DROP TABLE IF EXISTS
This commit is contained in:
@@ -103,6 +103,8 @@ export interface CreateTableStatement {
|
||||
export interface DropTableStatement {
|
||||
type: 'DROP_TABLE';
|
||||
name: string;
|
||||
/** IF EXISTS — 表不存在时不报错 */
|
||||
ifExists?: boolean;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -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
@@ -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 IN(NOT 后紧跟 LIKE 或 IN)
|
||||
if (this.curTokenIs(TokenType.NOT)) {
|
||||
if (this.peekTokenIs(TokenType.IN)) {
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user