From fa4621af4ba6a46bd6faaa4fb00fa2854dc2a1bf Mon Sep 17 00:00:00 2001 From: wenshao Date: Wed, 27 Jul 2016 10:52:30 +0800 Subject: [PATCH] improved mysql parser, support alter table union options --- .../ast/statement/SQLAlterTableStatement.java | 8 +++ .../mysql/parser/MySqlStatementParser.java | 11 +++- .../mysql/visitor/MySqlOutputVisitor.java | 30 +++++++++ .../bvt/sql/mysql/MySqlAlterTableTest26.java | 38 +++++++++++ .../bvt/sql/mysql/MySqlCreateTableTest73.java | 65 +++++++++++++++++++ 5 files changed, 151 insertions(+), 1 deletion(-) create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlAlterTableTest26.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlCreateTableTest73.java diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableStatement.java index e63e93c1fa..c14d9103ac 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableStatement.java @@ -16,9 +16,12 @@ package com.alibaba.druid.sql.ast.statement; import java.util.ArrayList; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; import com.alibaba.druid.sql.ast.SQLName; +import com.alibaba.druid.sql.ast.SQLObject; import com.alibaba.druid.sql.ast.SQLStatementImpl; import com.alibaba.druid.sql.visitor.SQLASTVisitor; @@ -35,6 +38,7 @@ public class SQLAlterTableStatement extends SQLStatementImpl implements SQLDDLSt private boolean removePatiting = false; private boolean upgradePatiting = false; + private Map tableOptions = new LinkedHashMap(); public SQLAlterTableStatement(){ @@ -114,6 +118,10 @@ public class SQLAlterTableStatement extends SQLStatementImpl implements SQLDDLSt this.setTableSource(new SQLExprTableSource(name)); } + public Map getTableOptions() { + return tableOptions; + } + @Override protected void accept0(SQLASTVisitor visitor) { if (visitor.visit(this)) { 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 0ad6ae4f6c..d26ec0224b 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 @@ -33,7 +33,6 @@ import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator; import com.alibaba.druid.sql.ast.expr.SQLCharExpr; import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr; -import com.alibaba.druid.sql.ast.expr.SQLListExpr; import com.alibaba.druid.sql.ast.expr.SQLLiteralExpr; import com.alibaba.druid.sql.ast.expr.SQLNCharExpr; import com.alibaba.druid.sql.ast.expr.SQLQueryExpr; @@ -2751,6 +2750,16 @@ public class MySqlStatementParser extends SQLStatementParser { } stmt.addItem(new MySqlAlterTableOption("COMMENT", '\'' + lexer.stringVal() + '\'')); lexer.nextToken(); + } else if (lexer.token() == Token.UNION) { + lexer.nextToken(); + if (lexer.token() == Token.EQ) { + lexer.nextToken(); + } + + accept(Token.LPAREN); + SQLTableSource tableSrc = this.createSQLSelectParser().parseTableSource(); + stmt.getTableOptions().put("UNION", tableSrc); + accept(Token.RPAREN); } else { break; } 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 93412e297d..3e471cbed9 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 @@ -2487,7 +2487,37 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV print0(ucase ? "UPGRADE PARTITIONING" : "upgrade partitioning"); } + if (x.getTableOptions().size() > 0) { + println(); + } + decrementIndent(); + + int i = 0; + for (Map.Entry option : x.getTableOptions().entrySet()) { + String key = option.getKey(); + if (i != 0) { + print(' '); + } + print0(ucase ? key : key.toLowerCase()); + + if ("TABLESPACE".equals(key)) { + print(' '); + option.getValue().accept(this); + continue; + } else if ("UNION".equals(key)) { + print0(" = ("); + option.getValue().accept(this); + print(')'); + continue; + } + + print0(" = "); + + option.getValue().accept(this); + i++; + } + return false; } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlAlterTableTest26.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlAlterTableTest26.java new file mode 100644 index 0000000000..47c915f7dd --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlAlterTableTest26.java @@ -0,0 +1,38 @@ +/* + * Copyright 1999-2101 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.druid.bvt.sql.mysql; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser; +import com.alibaba.druid.sql.parser.Token; + +public class MySqlAlterTableTest26 extends TestCase { + + public void test_alter_add_key() throws Exception { + String sql = "alter table xxxx UNION = (t1, t2);"; + MySqlStatementParser parser = new MySqlStatementParser(sql); + SQLStatement stmt = parser.parseStatementList().get(0); + parser.match(Token.EOF); + String output = SQLUtils.toMySqlString(stmt); + Assert.assertEquals("ALTER TABLE xxxx" + + "\n\tUNION = (t1, t2)", output); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlCreateTableTest73.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlCreateTableTest73.java new file mode 100644 index 0000000000..8bac3ecf36 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlCreateTableTest73.java @@ -0,0 +1,65 @@ +/* + * Copyright 1999-2101 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.druid.bvt.sql.mysql; + +import org.junit.Assert; +import org.junit.Test; + +import com.alibaba.druid.sql.MysqlTest; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser; +import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor; +import com.alibaba.druid.stat.TableStat.Column; + +public class MySqlCreateTableTest73 extends MysqlTest { + + @Test + public void test_one() throws Exception { + String sql = "CREATE TABLE total (" + + " id INT NOT NULL AUTO_INCREMENT," + + " message CHAR(20), INDEX(a))" + + " ENGINE=MERGE UNION=(t1,t2) INSERT_METHOD=LAST;"; + + MySqlStatementParser parser = new MySqlStatementParser(sql); + SQLStatement stmt = parser.parseCreateTable(); + + MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor(); + stmt.accept(visitor); + + Column column = visitor.getColumn("total", "id"); + Assert.assertNotNull(column); + Assert.assertEquals("INT", column.getDataType()); + + { + String output = SQLUtils.toMySqlString(stmt); + Assert.assertEquals("CREATE TABLE total (" + + "\n\tid INT NOT NULL AUTO_INCREMENT, " + + "\n\tmessage CHAR(20), " + + "\n\tINDEX(a)" + + "\n) ENGINE = MERGE UNION = (t1, t2) INSERT_METHOD = LAST", output); + } + + { + String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION); + Assert.assertEquals("create table total (" + + "\n\tid INT not null auto_increment, " + + "\n\tmessage CHAR(20), " + + "\n\tindex(a)" + + "\n) engine = MERGE union = (t1, t2) insert_method = LAST", output); + } + } +}