From c62b7286714f0d6ff662d063a1481ab0c7627687 Mon Sep 17 00:00:00 2001 From: Guoji Ma Date: Mon, 27 Nov 2017 14:00:18 +0800 Subject: [PATCH] parse the index hints clause containning multiple similar parts --- .../mysql/parser/MySqlSelectIntoParser.java | 13 +++- .../mysql/parser/MySqlSelectParser.java | 68 ++++++++----------- .../sql/mysql/select/MySqlSelectTest_90.java | 44 ++++++++++++ 3 files changed, 82 insertions(+), 43 deletions(-) create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/mysql/select/MySqlSelectTest_90.java diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlSelectIntoParser.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlSelectIntoParser.java index fc35681c3e..f947d2bddf 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlSelectIntoParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlSelectIntoParser.java @@ -277,11 +277,18 @@ public class MySqlSelectIntoParser extends SQLSelectParser { return tableSource; } - if (lexer.token() == Token.USE) { + parseIndexHintList(tableSource); + + return super.parseTableSourceRest(tableSource); + } + + private void parseIndexHintList(SQLTableSource tableSource) { + if (lexer.token() == Token.USE) { lexer.nextToken(); MySqlUseIndexHint hint = new MySqlUseIndexHint(); parseIndexHint(hint); tableSource.getHints().add(hint); + parseIndexHintList(tableSource); } if (lexer.identifierEquals("IGNORE")) { @@ -289,6 +296,7 @@ public class MySqlSelectIntoParser extends SQLSelectParser { MySqlIgnoreIndexHint hint = new MySqlIgnoreIndexHint(); parseIndexHint(hint); tableSource.getHints().add(hint); + parseIndexHintList(tableSource); } if (lexer.identifierEquals("FORCE")) { @@ -296,9 +304,8 @@ public class MySqlSelectIntoParser extends SQLSelectParser { MySqlForceIndexHint hint = new MySqlForceIndexHint(); parseIndexHint(hint); tableSource.getHints().add(hint); + parseIndexHintList(tableSource); } - - return super.parseTableSourceRest(tableSource); } private void parseIndexHint(MySqlIndexHintImpl hint) { diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlSelectParser.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlSelectParser.java index b6c3037a4e..627970a09f 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlSelectParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlSelectParser.java @@ -424,26 +424,7 @@ public class MySqlSelectParser extends SQLSelectParser { } protected SQLTableSource primaryTableSourceRest(SQLTableSource tableSource) { - if (lexer.token() == Token.USE) { - lexer.nextToken(); - MySqlUseIndexHint hint = new MySqlUseIndexHint(); - parseIndexHint(hint); - tableSource.getHints().add(hint); - } - - if (lexer.identifierEquals("IGNORE")) { - lexer.nextToken(); - MySqlIgnoreIndexHint hint = new MySqlIgnoreIndexHint(); - parseIndexHint(hint); - tableSource.getHints().add(hint); - } - - if (lexer.identifierEquals("FORCE")) { - lexer.nextToken(); - MySqlForceIndexHint hint = new MySqlForceIndexHint(); - parseIndexHint(hint); - tableSource.getHints().add(hint); - } + parseIndexHintList(tableSource); if (lexer.token() == Token.PARTITION) { lexer.nextToken(); @@ -460,26 +441,7 @@ public class MySqlSelectParser extends SQLSelectParser { return tableSource; } - if (lexer.token() == Token.USE) { - lexer.nextToken(); - MySqlUseIndexHint hint = new MySqlUseIndexHint(); - parseIndexHint(hint); - tableSource.getHints().add(hint); - } - - if (lexer.identifierEquals(FnvHash.Constants.IGNORE)) { - lexer.nextToken(); - MySqlIgnoreIndexHint hint = new MySqlIgnoreIndexHint(); - parseIndexHint(hint); - tableSource.getHints().add(hint); - } - - if (lexer.identifierEquals(FnvHash.Constants.FORCE)) { - lexer.nextToken(); - MySqlForceIndexHint hint = new MySqlForceIndexHint(); - parseIndexHint(hint); - tableSource.getHints().add(hint); - } + parseIndexHintList(tableSource); if (lexer.token() == Token.PARTITION) { lexer.nextToken(); @@ -491,6 +453,32 @@ public class MySqlSelectParser extends SQLSelectParser { return super.parseTableSourceRest(tableSource); } + private void parseIndexHintList(SQLTableSource tableSource) { + if (lexer.token() == Token.USE) { + lexer.nextToken(); + MySqlUseIndexHint hint = new MySqlUseIndexHint(); + parseIndexHint(hint); + tableSource.getHints().add(hint); + parseIndexHintList(tableSource); + } + + if (lexer.identifierEquals(FnvHash.Constants.IGNORE)) { + lexer.nextToken(); + MySqlIgnoreIndexHint hint = new MySqlIgnoreIndexHint(); + parseIndexHint(hint); + tableSource.getHints().add(hint); + parseIndexHintList(tableSource); + } + + if (lexer.identifierEquals(FnvHash.Constants.FORCE)) { + lexer.nextToken(); + MySqlForceIndexHint hint = new MySqlForceIndexHint(); + parseIndexHint(hint); + tableSource.getHints().add(hint); + parseIndexHintList(tableSource); + } + } + private void parseIndexHint(MySqlIndexHintImpl hint) { if (lexer.token() == Token.INDEX) { lexer.nextToken(); diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/select/MySqlSelectTest_90.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/select/MySqlSelectTest_90.java new file mode 100644 index 0000000000..8d56c2abf9 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/select/MySqlSelectTest_90.java @@ -0,0 +1,44 @@ +/* + * 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.select; + +import java.util.List; + +import org.junit.Assert; + +import com.alibaba.druid.sql.MysqlTest; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.ast.statement.SQLSelect; +import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock; +import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser; +import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor; +import com.alibaba.druid.stat.TableStat; + +public class MySqlSelectTest_90 extends MysqlTest { + + public void test_0() throws Exception { + String sql = "SELECT * FROM tbl_name use INDEX (idx1) use INDEX (idx2)"; + + MySqlStatementParser parser = new MySqlStatementParser(sql); + List statementList = parser.parseStatementList(); + + Assert.assertEquals(1, statementList.size()); + + String text = output(statementList); + Assert.assertEquals("SELECT *\nFROM tbl_name USE INDEX (idx1) USE INDEX (idx2)", text); + } +}