diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableExchangePartition.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableExchangePartition.java new file mode 100644 index 0000000000..147f61fdbc --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableExchangePartition.java @@ -0,0 +1,73 @@ +/* + * Copyright 1999-2017 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.sql.ast.statement; + +import com.alibaba.druid.sql.ast.SQLName; +import com.alibaba.druid.sql.ast.SQLObjectImpl; +import com.alibaba.druid.sql.visitor.SQLASTVisitor; + +public class SQLAlterTableExchangePartition extends SQLObjectImpl implements SQLAlterTableItem { + private SQLName partition; + private SQLExprTableSource table; + private Boolean validation; + + public SQLAlterTableExchangePartition() { + + } + + @Override + protected void accept0(SQLASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, partition); + acceptChild(visitor, table); + } + visitor.endVisit(this); + } + + public SQLName getPartition() { + return partition; + } + + public void setPartition(SQLName x) { + if (x != null) { + x.setParent(this); + } + this.partition = x; + } + + public SQLExprTableSource getTable() { + return table; + } + + public void setTable(SQLName x) { + setTable(new SQLExprTableSource(x)); + } + + public void setTable(SQLExprTableSource x) { + if (x != null) { + x.setParent(this); + } + this.table = x; + } + + public void setValidation(boolean validation) { + this.validation = validation; + } + + public Boolean getValidation() { + return validation; + } +} 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 18564d09b5..235dd32833 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 @@ -3806,7 +3806,31 @@ public class MySqlStatementParser extends SQLStatementParser { accept(Token.RPAREN); stmt.addItem(item); } else if (lexer.identifierEquals("EXCHANGE")) { - throw new ParserException("TODO " + lexer.info()); + lexer.nextToken(); + accept(Token.PARTITION); + + SQLAlterTableExchangePartition item = new SQLAlterTableExchangePartition(); + + SQLName partition = this.exprParser.name(); + item.setPartition(partition); + + accept(Token.WITH); + accept(Token.TABLE); + SQLName table = this.exprParser.name(); + item.setTable(table); + + if (lexer.token() == Token.WITH) { + lexer.nextToken(); + acceptIdentifier("VALIDATION"); + item.setValidation(true); + } else if (lexer.identifierEquals(FnvHash.Constants.WITHOUT)) { + lexer.nextToken(); + acceptIdentifier("VALIDATION"); + item.setValidation(false); + } + + + stmt.addItem(item); } else if (lexer.token() == Token.OPTIMIZE) { lexer.nextToken(); diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java index bafd60756e..fc01aef900 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -5192,7 +5192,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet if (x.isTablespace()) { print0(ucase ? " TABLESPACE" : " tablespace"); } - + return false; } @@ -6225,4 +6225,23 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet x.getTo().accept(this); return false; } + + @Override + public boolean visit(SQLAlterTableExchangePartition x) { + print0(ucase ? "EXCHANGE PARTITION " : "exchange partition "); + x.getPartition().accept(this); + print0(ucase ? " WITH TABLE " : " with table "); + x.getTable().accept(this); + + Boolean validation = x.getValidation(); + if (validation != null) { + if (validation) { + print0(ucase ? " WITH VALIDATION" : " with validation"); + } else { + print0(ucase ? " WITHOUT VALIDATION" : " without validation"); + } + } + + return false; + } } diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java index 2b44608700..bd8f5e31ea 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java @@ -823,4 +823,7 @@ public interface SQLASTVisitor { boolean visit(SQLAlterSequenceStatement x); void endVisit(SQLAlterSequenceStatement x); + + boolean visit(SQLAlterTableExchangePartition x); + void endVisit(SQLAlterTableExchangePartition x); } diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java index 2d82dcd832..4a51b91fcf 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java @@ -1944,6 +1944,16 @@ public class SQLASTVisitorAdapter implements SQLASTVisitor { } + @Override + public boolean visit(SQLAlterTableExchangePartition x) { + return true; + } + + @Override + public void endVisit(SQLAlterTableExchangePartition x) { + + } + public final boolean isEnabled(VisitorFeature feature) { return VisitorFeature.isEnabled(this.features, feature); } diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java index 606843e32f..870ce40550 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java @@ -2441,4 +2441,13 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { public boolean visit(SQLCreateDatabaseStatement x) { return false; } + + @Override + public boolean visit(SQLAlterTableExchangePartition x) { + SQLExprTableSource table = x.getTable(); + if (table != null) { + table.accept(this); + } + return false; + } } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/alter/MySqlAlterTableTest33.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/alter/MySqlAlterTableTest33.java new file mode 100644 index 0000000000..db63350a1b --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/alter/MySqlAlterTableTest33.java @@ -0,0 +1,37 @@ +/* + * Copyright 1999-2017 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.alter; + +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; +import junit.framework.TestCase; +import org.junit.Assert; + +public class MySqlAlterTableTest33 extends TestCase { + + public void test_alter_add_key() throws Exception { + String sql = "ALTER TABLE src.`part_tab` EXCHANGE PARTITION p9 WITH TABLE test_create_table without validation"; + MySqlStatementParser parser = new MySqlStatementParser(sql); + SQLStatement stmt = parser.parseStatementList().get(0); + parser.match(Token.EOF); + + String output = SQLUtils.toMySqlString(stmt); + Assert.assertEquals("ALTER TABLE src.`part_tab`\n" + + "\tEXCHANGE PARTITION p9 WITH TABLE test_create_table WITHOUT VALIDATION", output); + } +}