From 86a37cd1b561f484a8bcc0480c5493ec8ae8a37a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B8=A9=E5=B0=91?= Date: Wed, 16 May 2012 15:37:51 +0800 Subject: [PATCH] mysql parser refactor --- .../statement/MySqlAlterTableStatement.java | 20 ++- .../mysql/parser/MySqlStatementParser.java | 113 ++++++++++++--- .../mysql/visitor/MySqlASTVisitor.java | 133 +++++++++--------- .../mysql/visitor/MySqlASTVisitorAdapter.java | 11 ++ .../mysql/visitor/MySqlOutputVisitor.java | 24 ++++ .../mysql/visitor/MySqlSchemaStatVisitor.java | 11 ++ .../druid/sql/parser/SQLStatementParser.java | 2 +- .../druid/bvt/sql/cobar/DDLParserTest.java | 2 +- 8 files changed, 227 insertions(+), 89 deletions(-) diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlAlterTableStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlAlterTableStatement.java index 865d0b3470..b445e1b944 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlAlterTableStatement.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlAlterTableStatement.java @@ -4,11 +4,12 @@ import com.alibaba.druid.sql.ast.statement.SQLAlterTableStatement; import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor; import com.alibaba.druid.sql.visitor.SQLASTVisitor; - public class MySqlAlterTableStatement extends SQLAlterTableStatement { private static final long serialVersionUID = 1L; + private boolean ignore = false; + @Override protected void accept0(SQLASTVisitor visitor) { if (visitor instanceof MySqlASTVisitor) { @@ -17,8 +18,21 @@ public class MySqlAlterTableStatement extends SQLAlterTableStatement { throw new IllegalArgumentException("not support visitor type : " + visitor.getClass().getName()); } } - + public void accept0(MySqlASTVisitor visitor) { - throw new UnsupportedOperationException(this.getClass().getName()); + if (visitor.visit(this)) { + acceptChild(visitor, getTableSource()); + acceptChild(visitor, getItems()); + } + visitor.endVisit(this); } + + public boolean isIgnore() { + return ignore; + } + + public void setIgnore(boolean ignore) { + this.ignore = ignore; + } + } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java index 961842d6fc..3154230ed4 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java @@ -35,6 +35,7 @@ import com.alibaba.druid.sql.ast.statement.SQLTableSource; import com.alibaba.druid.sql.ast.statement.SQLUpdateSetItem; import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.CobarShowStatus; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlAlterTableStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlBinlogStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCommitStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateUserStatement; @@ -506,12 +507,12 @@ public class MySqlStatementParser extends SQLStatementParser { return stmt; } - + if (identifierEquals("VARIABLES")) { lexer.nextToken(); - + MySqlShowVariantsStatement stmt = parseShowVariants(); - + return stmt; } @@ -524,7 +525,7 @@ public class MySqlStatementParser extends SQLStatementParser { stmt.setGlobal(true); return stmt; } - + if (identifierEquals("VARIABLES")) { lexer.nextToken(); MySqlShowVariantsStatement stmt = parseShowVariants(); @@ -542,7 +543,7 @@ public class MySqlStatementParser extends SQLStatementParser { stmt.setSession(true); return stmt; } - + if (identifierEquals("VARIABLES")) { lexer.nextToken(); MySqlShowVariantsStatement stmt = parseShowVariants(); @@ -970,24 +971,24 @@ public class MySqlStatementParser extends SQLStatementParser { return stmt; } - + if (identifierEquals("RELAYLOG")) { lexer.nextToken(); acceptIdentifier("EVENTS"); MySqlShowRelayLogEventsStatement stmt = new MySqlShowRelayLogEventsStatement(); - + if (lexer.token() == Token.IN) { lexer.nextToken(); stmt.setLogName(this.exprParser.primary()); } - + if (lexer.token() == Token.FROM) { lexer.nextToken(); stmt.setFrom(this.exprParser.primary()); } - + stmt.setLimit(this.parseLimit()); - + return stmt; } @@ -1022,7 +1023,7 @@ public class MySqlStatementParser extends SQLStatementParser { return stmt; } } - + if (lexer.token() == Token.TABLE) { lexer.nextToken(); acceptIdentifier("STATUS"); @@ -1031,7 +1032,7 @@ public class MySqlStatementParser extends SQLStatementParser { lexer.nextToken(); stmt.setDatabase(this.exprParser.name()); } - + if (lexer.token() == Token.LIKE) { lexer.nextToken(); stmt.setLike(this.exprParser.expr()); @@ -1041,10 +1042,10 @@ public class MySqlStatementParser extends SQLStatementParser { lexer.nextToken(); stmt.setWhere(this.exprParser.expr()); } - + return stmt; } - + if (identifierEquals("TRIGGERS")) { lexer.nextToken(); MySqlShowTriggersStatement stmt = new MySqlShowTriggersStatement(); @@ -1091,22 +1092,22 @@ public class MySqlStatementParser extends SQLStatementParser { return stmt; } - + private MySqlShowVariantsStatement parseShowVariants() throws ParserException { MySqlShowVariantsStatement stmt = new MySqlShowVariantsStatement(); - + if (lexer.token() == Token.LIKE) { lexer.nextToken(); SQLExpr like = exprParser.expr(); stmt.setLike(like); } - + if (lexer.token() == Token.WHERE) { lexer.nextToken(); SQLExpr where = exprParser.expr(); stmt.setWhere(where); } - + return stmt; } @@ -1785,9 +1786,81 @@ public class MySqlStatementParser extends SQLStatementParser { return null; } - - public SQLSetStatement parseAlter() { + + public SQLStatement parseAlter() { accept(Token.ALTER); + + boolean ignore = false; + + if (identifierEquals("IGNORE")) { + ignore = true; + lexer.nextToken(); + } + + if (lexer.token() == Token.TABLE) { + lexer.nextToken(); + + MySqlAlterTableStatement stmt = new MySqlAlterTableStatement(); + stmt.setIgnore(ignore); + stmt.setName(this.exprParser.name()); + + for (;;) { + if (identifierEquals("ADD")) { + throw new ParserException("TODO " + lexer.token() + " " + lexer.stringVal()); + } else if (identifierEquals("ALTER")) { + throw new ParserException("TODO " + lexer.token() + " " + lexer.stringVal()); + } else if (identifierEquals("CHANGE")) { + throw new ParserException("TODO " + lexer.token() + " " + lexer.stringVal()); + } else if (identifierEquals("MODIFY")) { + throw new ParserException("TODO " + lexer.token() + " " + lexer.stringVal()); + } else if (identifierEquals("DROP")) { + throw new ParserException("TODO " + lexer.token() + " " + lexer.stringVal()); + } else if (identifierEquals("DISABLE")) { + throw new ParserException("TODO " + lexer.token() + " " + lexer.stringVal()); + } else if (identifierEquals("ENABLE")) { + throw new ParserException("TODO " + lexer.token() + " " + lexer.stringVal()); + } else if (identifierEquals("RENAME")) { + throw new ParserException("TODO " + lexer.token() + " " + lexer.stringVal()); + } else if (lexer.token() == Token.ORDER) { + throw new ParserException("TODO " + lexer.token() + " " + lexer.stringVal()); + } else if (identifierEquals("CONVERT")) { + throw new ParserException("TODO " + lexer.token() + " " + lexer.stringVal()); + } else if (lexer.token() == Token.DEFAULT) { + throw new ParserException("TODO " + lexer.token() + " " + lexer.stringVal()); + } else if (identifierEquals("DISCARD")) { + throw new ParserException("TODO " + lexer.token() + " " + lexer.stringVal()); + } else if (identifierEquals("IMPORT")) { + throw new ParserException("TODO " + lexer.token() + " " + lexer.stringVal()); + } else if (identifierEquals("FORCE")) { + throw new ParserException("TODO " + lexer.token() + " " + lexer.stringVal()); + } else if (identifierEquals("TRUNCATE")) { + throw new ParserException("TODO " + lexer.token() + " " + lexer.stringVal()); + } else if (identifierEquals("COALESCE")) { + throw new ParserException("TODO " + lexer.token() + " " + lexer.stringVal()); + + } else if (identifierEquals("REORGANIZE")) { + throw new ParserException("TODO " + lexer.token() + " " + lexer.stringVal()); + } else if (identifierEquals("EXCHANGE")) { + throw new ParserException("TODO " + lexer.token() + " " + lexer.stringVal()); + } else if (identifierEquals("ANALYZE")) { + throw new ParserException("TODO " + lexer.token() + " " + lexer.stringVal()); + } else if (identifierEquals("CHECK")) { + throw new ParserException("TODO " + lexer.token() + " " + lexer.stringVal()); + } else if (identifierEquals("OPTIMIZE")) { + throw new ParserException("TODO " + lexer.token() + " " + lexer.stringVal()); + } else if (identifierEquals("REBUILD")) { + throw new ParserException("TODO " + lexer.token() + " " + lexer.stringVal()); + } else if (identifierEquals("REPAIR")) { + throw new ParserException("TODO " + lexer.token() + " " + lexer.stringVal()); + } else if (identifierEquals("REMOVE")) { + throw new ParserException("TODO " + lexer.token() + " " + lexer.stringVal()); + } else { + break; + } + } + + return stmt; + } throw new ParserException("TODO " + lexer.token() + " " + lexer.stringVal()); } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitor.java index d90c1600a2..0a38d7e5a8 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitor.java @@ -25,6 +25,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlMatchAgainstExpr; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlOutFileExpr; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlUserName; import com.alibaba.druid.sql.dialect.mysql.ast.statement.CobarShowStatus; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlAlterTableStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlBinlogStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCommitStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateUserStatement; @@ -288,132 +289,136 @@ public interface MySqlASTVisitor extends SQLASTVisitor { boolean visit(MySqlShowContributorsStatement x); void endVisit(MySqlShowContributorsStatement x); - + boolean visit(MySqlShowCreateDatabaseStatement x); - + void endVisit(MySqlShowCreateDatabaseStatement x); - + boolean visit(MySqlShowCreateEventStatement x); - + void endVisit(MySqlShowCreateEventStatement x); - + boolean visit(MySqlShowCreateFunctionStatement x); - + void endVisit(MySqlShowCreateFunctionStatement x); - + boolean visit(MySqlShowCreateProcedureStatement x); - + void endVisit(MySqlShowCreateProcedureStatement x); - + boolean visit(MySqlShowCreateTableStatement x); - + void endVisit(MySqlShowCreateTableStatement x); - + boolean visit(MySqlShowCreateTriggerStatement x); - + void endVisit(MySqlShowCreateTriggerStatement x); - + boolean visit(MySqlShowCreateViewStatement x); - + void endVisit(MySqlShowCreateViewStatement x); - + boolean visit(MySqlShowEngineStatement x); - + void endVisit(MySqlShowEngineStatement x); - + boolean visit(MySqlShowEnginesStatement x); - + void endVisit(MySqlShowEnginesStatement x); - + boolean visit(MySqlShowErrorsStatement x); - + void endVisit(MySqlShowErrorsStatement x); - + boolean visit(MySqlShowEventsStatement x); - + void endVisit(MySqlShowEventsStatement x); - + boolean visit(MySqlShowFunctionCodeStatement x); - + void endVisit(MySqlShowFunctionCodeStatement x); - + boolean visit(MySqlShowFunctionStatusStatement x); - + void endVisit(MySqlShowFunctionStatusStatement x); - + boolean visit(MySqlShowGrantsStatement x); - + void endVisit(MySqlShowGrantsStatement x); - + boolean visit(MySqlUserName x); - + void endVisit(MySqlUserName x); - + boolean visit(MySqlShowIndexesStatement x); - + void endVisit(MySqlShowIndexesStatement x); - + boolean visit(MySqlShowKeysStatement x); - + void endVisit(MySqlShowKeysStatement x); - + boolean visit(MySqlShowMasterStatusStatement x); - + void endVisit(MySqlShowMasterStatusStatement x); - + boolean visit(MySqlShowOpenTablesStatement x); - + void endVisit(MySqlShowOpenTablesStatement x); - + boolean visit(MySqlShowPluginsStatement x); - + void endVisit(MySqlShowPluginsStatement x); - + boolean visit(MySqlShowPrivilegesStatement x); - + void endVisit(MySqlShowPrivilegesStatement x); - + boolean visit(MySqlShowProcedureCodeStatement x); - + void endVisit(MySqlShowProcedureCodeStatement x); - + boolean visit(MySqlShowProcedureStatusStatement x); - + void endVisit(MySqlShowProcedureStatusStatement x); - + boolean visit(MySqlShowProcessListStatement x); - + void endVisit(MySqlShowProcessListStatement x); - + boolean visit(MySqlShowProfileStatement x); - + void endVisit(MySqlShowProfileStatement x); - + boolean visit(MySqlShowProfilesStatement x); - + void endVisit(MySqlShowProfilesStatement x); - + boolean visit(MySqlShowRelayLogEventsStatement x); - + void endVisit(MySqlShowRelayLogEventsStatement x); - + boolean visit(MySqlShowSlaveHostsStatement x); - + void endVisit(MySqlShowSlaveHostsStatement x); - + boolean visit(MySqlShowSlaveStatusStatement x); - + void endVisit(MySqlShowSlaveStatusStatement x); - + boolean visit(MySqlShowTableStatusStatement x); - + void endVisit(MySqlShowTableStatusStatement x); - + boolean visit(MySqlShowTriggersStatement x); - + void endVisit(MySqlShowTriggersStatement x); - + boolean visit(MySqlShowVariantsStatement x); - + void endVisit(MySqlShowVariantsStatement x); + + boolean visit(MySqlAlterTableStatement x); + + void endVisit(MySqlAlterTableStatement x); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitorAdapter.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitorAdapter.java index 20fb42b45a..0b6198de4c 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitorAdapter.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitorAdapter.java @@ -10,6 +10,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlMatchAgainstExpr; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlOutFileExpr; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlUserName; import com.alibaba.druid.sql.dialect.mysql.ast.statement.CobarShowStatus; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlAlterTableStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlBinlogStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCommitStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateUserStatement; @@ -904,4 +905,14 @@ public class MySqlASTVisitorAdapter extends SQLASTVisitorAdapter implements public void endVisit(MySqlShowVariantsStatement x) { } + + @Override + public boolean visit(MySqlAlterTableStatement x) { + return true; + } + + @Override + public void endVisit(MySqlAlterTableStatement x) { + + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java index 2593499298..eb58811b00 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java @@ -23,6 +23,7 @@ import com.alibaba.druid.sql.ast.SQLSetQuantifier; import com.alibaba.druid.sql.ast.expr.SQLCharExpr; import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr; import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr; +import com.alibaba.druid.sql.ast.statement.SQLAlterTableItem; import com.alibaba.druid.sql.ast.statement.SQLCharactorDataType; import com.alibaba.druid.sql.ast.statement.SQLColumnConstraint; import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition; @@ -40,6 +41,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlMatchAgainstExpr; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlOutFileExpr; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlUserName; import com.alibaba.druid.sql.dialect.mysql.ast.statement.CobarShowStatus; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlAlterTableStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlBinlogStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCommitStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement; @@ -2163,4 +2165,26 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV public void endVisit(MySqlShowVariantsStatement x) { } + + @Override + public boolean visit(MySqlAlterTableStatement x) { + if (x.isIgnore()) { + print("ALTER IGNORE TABLE "); + } else { + print("ALTER TABLE "); + } + x.getName().accept(this); + incrementIndent(); + for (SQLAlterTableItem item : x.getItems()) { + println(); + item.accept(this); + } + decrementIndent(); + return false; + } + + @Override + public void endVisit(MySqlAlterTableStatement x) { + + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlSchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlSchemaStatVisitor.java index ce44fdede5..935570adeb 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlSchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlSchemaStatVisitor.java @@ -19,6 +19,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlMatchAgainstExpr; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlOutFileExpr; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlUserName; import com.alibaba.druid.sql.dialect.mysql.ast.statement.CobarShowStatus; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlAlterTableStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlBinlogStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCommitStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateUserStatement; @@ -967,4 +968,14 @@ public class MySqlSchemaStatVisitor extends SchemaStatVisitor implements MySqlAS public void endVisit(MySqlShowVariantsStatement x) { } + + @Override + public boolean visit(MySqlAlterTableStatement x) { + return false; + } + + @Override + public void endVisit(MySqlAlterTableStatement x) { + + } } diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java index 2955108ffd..ee43707757 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java @@ -164,7 +164,7 @@ public class SQLStatementParser extends SQLParser { return stmt; } - public SQLSetStatement parseAlter() { + public SQLStatement parseAlter() { accept(Token.ALTER); throw new ParserException("TODO " + lexer.token() + " " + lexer.stringVal()); } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/cobar/DDLParserTest.java b/src/test/java/com/alibaba/druid/bvt/sql/cobar/DDLParserTest.java index 5836f3aed4..44edae6ad3 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/cobar/DDLParserTest.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/cobar/DDLParserTest.java @@ -41,7 +41,7 @@ public class DDLParserTest extends TestCase { SQLStatement stmt = parser.parseStatementList().get(0); parser.match(Token.EOF); String output = SQLUtils.toMySqlString(stmt); - Assert.assertEquals("ALTER ignore table tb_name", output); + Assert.assertEquals("ALTER IGNORE TABLE tb_name", output); } // public void testDDLStmt() throws Exception {