feat: SQL 语法支持 CREATE TABLE IF NOT EXISTS
- Parser 支持 CREATE TABLE IF NOT EXISTS 语法 - AST CreateTableStatement 新增 ifNotExists 字段 - Executor 表已存在时静默跳过 - 修复 demo.html Aria 预设报错
This commit is contained in:
Vendored
+15
-1
@@ -4001,6 +4001,12 @@ class QueryExecutor {
|
|||||||
return this.engine.delete(plan.table, plan);
|
return this.engine.delete(plan.table, plan);
|
||||||
}
|
}
|
||||||
async executeCreateTable(stmt) {
|
async executeCreateTable(stmt) {
|
||||||
|
// IF NOT EXISTS: 表已存在时静默返回
|
||||||
|
if (stmt.ifNotExists) {
|
||||||
|
const exists = await this.engine.hasTable(stmt.name);
|
||||||
|
if (exists)
|
||||||
|
return;
|
||||||
|
}
|
||||||
const columns = {};
|
const columns = {};
|
||||||
for (const col of stmt.columns)
|
for (const col of stmt.columns)
|
||||||
columns[col.name] = astColumnToColumnDef(col);
|
columns[col.name] = astColumnToColumnDef(col);
|
||||||
@@ -4763,6 +4769,14 @@ class Parser {
|
|||||||
parseCreateTable() {
|
parseCreateTable() {
|
||||||
this.expect(TokenType.CREATE);
|
this.expect(TokenType.CREATE);
|
||||||
this.expect(TokenType.TABLE);
|
this.expect(TokenType.TABLE);
|
||||||
|
// IF NOT EXISTS(可选)
|
||||||
|
let ifNotExists = false;
|
||||||
|
if (this.curTokenIs(TokenType.IF)) {
|
||||||
|
this.nextToken();
|
||||||
|
this.expect(TokenType.NOT);
|
||||||
|
this.expect(TokenType.EXISTS);
|
||||||
|
ifNotExists = true;
|
||||||
|
}
|
||||||
const tableName = this.expectIdentifier('table name');
|
const tableName = this.expectIdentifier('table name');
|
||||||
this.expect(TokenType.LPAREN);
|
this.expect(TokenType.LPAREN);
|
||||||
const columns = [];
|
const columns = [];
|
||||||
@@ -4772,7 +4786,7 @@ class Parser {
|
|||||||
columns.push(this.parseColumnDef());
|
columns.push(this.parseColumnDef());
|
||||||
} while (this.curTokenIs(TokenType.COMMA));
|
} while (this.curTokenIs(TokenType.COMMA));
|
||||||
this.expect(TokenType.RPAREN);
|
this.expect(TokenType.RPAREN);
|
||||||
return { type: 'CREATE_TABLE', name: tableName, columns };
|
return { type: 'CREATE_TABLE', name: tableName, columns, ifNotExists: ifNotExists || undefined };
|
||||||
}
|
}
|
||||||
parseColumnDef() {
|
parseColumnDef() {
|
||||||
const name = this.expectIdentifier('column name');
|
const name = this.expectIdentifier('column name');
|
||||||
|
|||||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+2
@@ -224,6 +224,8 @@ interface CreateTableStatement {
|
|||||||
type: 'CREATE_TABLE';
|
type: 'CREATE_TABLE';
|
||||||
name: string;
|
name: string;
|
||||||
columns: ASTColumnDef[];
|
columns: ASTColumnDef[];
|
||||||
|
/** IF NOT EXISTS — 表已存在时不报错 */
|
||||||
|
ifNotExists?: boolean;
|
||||||
}
|
}
|
||||||
interface DropTableStatement {
|
interface DropTableStatement {
|
||||||
type: 'DROP_TABLE';
|
type: 'DROP_TABLE';
|
||||||
|
|||||||
Vendored
+15
-1
@@ -3997,6 +3997,12 @@ class QueryExecutor {
|
|||||||
return this.engine.delete(plan.table, plan);
|
return this.engine.delete(plan.table, plan);
|
||||||
}
|
}
|
||||||
async executeCreateTable(stmt) {
|
async executeCreateTable(stmt) {
|
||||||
|
// IF NOT EXISTS: 表已存在时静默返回
|
||||||
|
if (stmt.ifNotExists) {
|
||||||
|
const exists = await this.engine.hasTable(stmt.name);
|
||||||
|
if (exists)
|
||||||
|
return;
|
||||||
|
}
|
||||||
const columns = {};
|
const columns = {};
|
||||||
for (const col of stmt.columns)
|
for (const col of stmt.columns)
|
||||||
columns[col.name] = astColumnToColumnDef(col);
|
columns[col.name] = astColumnToColumnDef(col);
|
||||||
@@ -4759,6 +4765,14 @@ class Parser {
|
|||||||
parseCreateTable() {
|
parseCreateTable() {
|
||||||
this.expect(TokenType.CREATE);
|
this.expect(TokenType.CREATE);
|
||||||
this.expect(TokenType.TABLE);
|
this.expect(TokenType.TABLE);
|
||||||
|
// IF NOT EXISTS(可选)
|
||||||
|
let ifNotExists = false;
|
||||||
|
if (this.curTokenIs(TokenType.IF)) {
|
||||||
|
this.nextToken();
|
||||||
|
this.expect(TokenType.NOT);
|
||||||
|
this.expect(TokenType.EXISTS);
|
||||||
|
ifNotExists = true;
|
||||||
|
}
|
||||||
const tableName = this.expectIdentifier('table name');
|
const tableName = this.expectIdentifier('table name');
|
||||||
this.expect(TokenType.LPAREN);
|
this.expect(TokenType.LPAREN);
|
||||||
const columns = [];
|
const columns = [];
|
||||||
@@ -4768,7 +4782,7 @@ class Parser {
|
|||||||
columns.push(this.parseColumnDef());
|
columns.push(this.parseColumnDef());
|
||||||
} while (this.curTokenIs(TokenType.COMMA));
|
} while (this.curTokenIs(TokenType.COMMA));
|
||||||
this.expect(TokenType.RPAREN);
|
this.expect(TokenType.RPAREN);
|
||||||
return { type: 'CREATE_TABLE', name: tableName, columns };
|
return { type: 'CREATE_TABLE', name: tableName, columns, ifNotExists: ifNotExists || undefined };
|
||||||
}
|
}
|
||||||
parseColumnDef() {
|
parseColumnDef() {
|
||||||
const name = this.expectIdentifier('column name');
|
const name = this.expectIdentifier('column name');
|
||||||
|
|||||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+15
-1
@@ -4003,6 +4003,12 @@
|
|||||||
return this.engine.delete(plan.table, plan);
|
return this.engine.delete(plan.table, plan);
|
||||||
}
|
}
|
||||||
async executeCreateTable(stmt) {
|
async executeCreateTable(stmt) {
|
||||||
|
// IF NOT EXISTS: 表已存在时静默返回
|
||||||
|
if (stmt.ifNotExists) {
|
||||||
|
const exists = await this.engine.hasTable(stmt.name);
|
||||||
|
if (exists)
|
||||||
|
return;
|
||||||
|
}
|
||||||
const columns = {};
|
const columns = {};
|
||||||
for (const col of stmt.columns)
|
for (const col of stmt.columns)
|
||||||
columns[col.name] = astColumnToColumnDef(col);
|
columns[col.name] = astColumnToColumnDef(col);
|
||||||
@@ -4765,6 +4771,14 @@
|
|||||||
parseCreateTable() {
|
parseCreateTable() {
|
||||||
this.expect(TokenType.CREATE);
|
this.expect(TokenType.CREATE);
|
||||||
this.expect(TokenType.TABLE);
|
this.expect(TokenType.TABLE);
|
||||||
|
// IF NOT EXISTS(可选)
|
||||||
|
let ifNotExists = false;
|
||||||
|
if (this.curTokenIs(TokenType.IF)) {
|
||||||
|
this.nextToken();
|
||||||
|
this.expect(TokenType.NOT);
|
||||||
|
this.expect(TokenType.EXISTS);
|
||||||
|
ifNotExists = true;
|
||||||
|
}
|
||||||
const tableName = this.expectIdentifier('table name');
|
const tableName = this.expectIdentifier('table name');
|
||||||
this.expect(TokenType.LPAREN);
|
this.expect(TokenType.LPAREN);
|
||||||
const columns = [];
|
const columns = [];
|
||||||
@@ -4774,7 +4788,7 @@
|
|||||||
columns.push(this.parseColumnDef());
|
columns.push(this.parseColumnDef());
|
||||||
} while (this.curTokenIs(TokenType.COMMA));
|
} while (this.curTokenIs(TokenType.COMMA));
|
||||||
this.expect(TokenType.RPAREN);
|
this.expect(TokenType.RPAREN);
|
||||||
return { type: 'CREATE_TABLE', name: tableName, columns };
|
return { type: 'CREATE_TABLE', name: tableName, columns, ifNotExists: ifNotExists || undefined };
|
||||||
}
|
}
|
||||||
parseColumnDef() {
|
parseColumnDef() {
|
||||||
const name = this.expectIdentifier('column name');
|
const name = this.expectIdentifier('column name');
|
||||||
|
|||||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
@@ -94,6 +94,8 @@ export interface CreateTableStatement {
|
|||||||
type: 'CREATE_TABLE';
|
type: 'CREATE_TABLE';
|
||||||
name: string;
|
name: string;
|
||||||
columns: ASTColumnDef[];
|
columns: ASTColumnDef[];
|
||||||
|
/** IF NOT EXISTS — 表已存在时不报错 */
|
||||||
|
ifNotExists?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -228,6 +228,11 @@ export class QueryExecutor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async executeCreateTable(stmt: CreateTableStatement): Promise<void> {
|
private async executeCreateTable(stmt: CreateTableStatement): Promise<void> {
|
||||||
|
// IF NOT EXISTS: 表已存在时静默返回
|
||||||
|
if (stmt.ifNotExists) {
|
||||||
|
const exists = await this.engine.hasTable(stmt.name);
|
||||||
|
if (exists) return;
|
||||||
|
}
|
||||||
const columns: Record<string, any> = {};
|
const columns: Record<string, any> = {};
|
||||||
for (const col of stmt.columns) columns[col.name] = astColumnToColumnDef(col);
|
for (const col of stmt.columns) columns[col.name] = astColumnToColumnDef(col);
|
||||||
return this.engine.createTable(createSchema(stmt.name, columns));
|
return this.engine.createTable(createSchema(stmt.name, columns));
|
||||||
|
|||||||
+11
-1
@@ -327,6 +327,16 @@ export class Parser {
|
|||||||
private parseCreateTable(): CreateTableStatement {
|
private parseCreateTable(): CreateTableStatement {
|
||||||
this.expect(TokenType.CREATE);
|
this.expect(TokenType.CREATE);
|
||||||
this.expect(TokenType.TABLE);
|
this.expect(TokenType.TABLE);
|
||||||
|
|
||||||
|
// IF NOT EXISTS(可选)
|
||||||
|
let ifNotExists = false;
|
||||||
|
if (this.curTokenIs(TokenType.IF)) {
|
||||||
|
this.nextToken();
|
||||||
|
this.expect(TokenType.NOT);
|
||||||
|
this.expect(TokenType.EXISTS);
|
||||||
|
ifNotExists = true;
|
||||||
|
}
|
||||||
|
|
||||||
const tableName = this.expectIdentifier('table name');
|
const tableName = this.expectIdentifier('table name');
|
||||||
this.expect(TokenType.LPAREN);
|
this.expect(TokenType.LPAREN);
|
||||||
|
|
||||||
@@ -338,7 +348,7 @@ export class Parser {
|
|||||||
|
|
||||||
this.expect(TokenType.RPAREN);
|
this.expect(TokenType.RPAREN);
|
||||||
|
|
||||||
return { type: 'CREATE_TABLE', name: tableName, columns };
|
return { type: 'CREATE_TABLE', name: tableName, columns, ifNotExists: ifNotExists || undefined };
|
||||||
}
|
}
|
||||||
|
|
||||||
private parseColumnDef(): ASTColumnDef {
|
private parseColumnDef(): ASTColumnDef {
|
||||||
|
|||||||
Reference in New Issue
Block a user