From 132ecc99e82ae9e437ffe80b139270abc19de45c Mon Sep 17 00:00:00 2001 From: wenshao Date: Wed, 7 Mar 2018 14:52:38 +0800 Subject: [PATCH] improved mysql parser, support checksum table syntax. --- .../MySqlChecksumTableStatement.java | 54 +++++++++++++++++++ .../mysql/parser/MySqlStatementParser.java | 34 ++++++++++++ .../mysql/visitor/MySqlASTVisitor.java | 3 ++ .../mysql/visitor/MySqlASTVisitorAdapter.java | 10 ++++ .../mysql/visitor/MySqlOutputVisitor.java | 12 +++++ .../mysql/visitor/MySqlSchemaStatVisitor.java | 10 ++++ .../java/com/alibaba/druid/util/FnvHash.java | 1 + .../bvt/sql/mysql/MySqlChecksumTableTest.java | 46 ++++++++++++++++ 8 files changed, 170 insertions(+) create mode 100644 src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlChecksumTableStatement.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlChecksumTableTest.java diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlChecksumTableStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlChecksumTableStatement.java new file mode 100644 index 0000000000..7a2a99b5e8 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlChecksumTableStatement.java @@ -0,0 +1,54 @@ +package com.alibaba.druid.sql.dialect.mysql.ast.statement; + +import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; +import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor; + +import java.util.ArrayList; +import java.util.List; + +public class MySqlChecksumTableStatement extends MySqlStatementImpl { + private final List tables = new ArrayList(); + + private boolean quick; + private boolean extended; + + public MySqlChecksumTableStatement() { + + } + + public void addTable(SQLExprTableSource table) { + if (table == null) { + return; + } + + table.setParent(this); + tables.add(table); + } + + public List getTables() { + return tables; + } + + public boolean isQuick() { + return quick; + } + + public void setQuick(boolean quick) { + this.quick = quick; + } + + public boolean isExtended() { + return extended; + } + + public void setExtended(boolean extended) { + this.extended = extended; + } + + public void accept0(MySqlASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, tables); + } + visitor.endVisit(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 a88b8e335f..e7725b0243 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 @@ -851,6 +851,11 @@ public class MySqlStatementParser extends SQLStatementParser { return true; } + if (lexer.identifierEquals(FnvHash.Constants.CHECKSUM)) { + statementList.add(this.parseChecksum()); + return true; + } + if (lexer.token() == Token.HINT) { List hints = this.exprParser.parseHints(); @@ -4662,6 +4667,11 @@ public class MySqlStatementParser extends SQLStatementParser { continue; } + if (lexer.identifierEquals(FnvHash.Constants.CHECKSUM)) { + statementList.add(this.parseChecksum()); + continue; + } + if (lexer.token() == Token.IDENTIFIER) { String label = lexer.stringVal(); char ch = lexer.current(); @@ -4693,6 +4703,30 @@ public class MySqlStatementParser extends SQLStatementParser { } + + public MySqlChecksumTableStatement parseChecksum() { + MySqlChecksumTableStatement stmt = new MySqlChecksumTableStatement(); + if (lexer.identifierEquals(FnvHash.Constants.CHECKSUM)) { + lexer.nextToken(); + } else { + throw new ParserException("TODO " + lexer.info()); + } + + for (;;) { + SQLExprTableSource table = (SQLExprTableSource) this.createSQLSelectParser().parseTableSource(); + stmt.addTable(table); + + if (lexer.token() == Token.COMMA) { + lexer.nextToken(); + continue; + } + + break; + } + + return stmt; + } + /** * parse if statement * 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 6225d62714..340ff1b87c 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 @@ -494,4 +494,7 @@ public interface MySqlASTVisitor extends SQLASTVisitor { boolean visit(MySqlShowDatabasePartitionStatusStatement x); void endVisit(MySqlShowDatabasePartitionStatusStatement x); + boolean visit(MySqlChecksumTableStatement x); + void endVisit(MySqlChecksumTableStatement 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 31f4c0007b..34ae78d4d4 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 @@ -1228,4 +1228,14 @@ public class MySqlASTVisitorAdapter extends SQLASTVisitorAdapter implements MySq } + @Override + public boolean visit(MySqlChecksumTableStatement x) { + return true; + } + + @Override + public void endVisit(MySqlChecksumTableStatement 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 e6554ba2fc..67ea3a9d4a 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 @@ -4200,4 +4200,16 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV } } } + + @Override + public void endVisit(MySqlChecksumTableStatement x) { + + } + + @Override + public boolean visit(MySqlChecksumTableStatement x) { + print0(ucase ? "CHECKSUM TABLE " : "checksum table "); + printAndAccept(x.getTables(), ","); + return false; + } } // 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 1799ae1ca5..4d5bfb4ffd 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 @@ -1361,4 +1361,14 @@ public class MySqlSchemaStatVisitor extends SchemaStatVisitor implements MySqlAS public void endVisit(MySqlShowDatabasePartitionStatusStatement x) { } + + @Override + public boolean visit(MySqlChecksumTableStatement x) { + return true; + } + + @Override + public void endVisit(MySqlChecksumTableStatement x) { + + } } diff --git a/src/main/java/com/alibaba/druid/util/FnvHash.java b/src/main/java/com/alibaba/druid/util/FnvHash.java index 04e8f22946..6348f69437 100644 --- a/src/main/java/com/alibaba/druid/util/FnvHash.java +++ b/src/main/java/com/alibaba/druid/util/FnvHash.java @@ -638,5 +638,6 @@ public final class FnvHash { long PATH = fnv1a_64_lower("PATH"); long COMPRESSION = fnv1a_64_lower("COMPRESSION"); long KEY_BLOCK_SIZE = fnv1a_64_lower("KEY_BLOCK_SIZE"); + long CHECKSUM = fnv1a_64_lower("CHECKSUM"); } } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlChecksumTableTest.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlChecksumTableTest.java new file mode 100644 index 0000000000..cc7e9597e7 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlChecksumTableTest.java @@ -0,0 +1,46 @@ +/* + * 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; + +import com.alibaba.druid.sql.MysqlTest; +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 java.util.List; + +public class MySqlChecksumTableTest extends MysqlTest { + + public void test_0() throws Exception { + String sql = "CHECKSUM TABLE tbl_name"; + + MySqlStatementParser parser = new MySqlStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement stmt = statementList.get(0); + + assertEquals(1, statementList.size()); + + MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor(); + stmt.accept(visitor); + + assertEquals(1, visitor.getTables().size()); + assertEquals(0, visitor.getColumns().size()); + assertEquals(0, visitor.getConditions().size()); + assertEquals(0, visitor.getOrderByColumns().size()); + + assertEquals("CHECKSUM TABLE TABLE tbl_name", stmt.toString()); + } +}