From b5ee153efec70bcc06b2eb117206cd3fac82c616 Mon Sep 17 00:00:00 2001 From: wenshao Date: Mon, 12 Feb 2018 17:43:01 +0800 Subject: [PATCH] bug fixed for mysql parser create function. for issue #2340 --- .../mysql/parser/MySqlStatementParser.java | 28 ++++---- .../druid/sql/parser/SQLExprParser.java | 10 +++ .../druid/sql/parser/SQLStatementParser.java | 6 +- .../MySql_Create_Function_1.java | 69 +++++++++++++++++++ 4 files changed, 99 insertions(+), 14 deletions(-) create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/mysql/create_function/MySql_Create_Function_1.java 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 07df692fad..a0e1421cee 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 @@ -318,6 +318,9 @@ public class MySqlStatementParser extends SQLStatementParser { } else if (lexer.token() == Token.VIEW) { lexer.reset(markBp, markChar, Token.CREATE); return parseCreateView(); + } else if (lexer.token() == Token.FUNCTION) { + lexer.reset(markBp, markChar, Token.CREATE); + return parseCreateFunction(); } else { lexer.reset(markBp, markChar, Token.CREATE); return parseCreateProcedure(); @@ -4282,22 +4285,23 @@ public class MySqlStatementParser extends SQLStatementParser { SQLCreateFunctionStatement stmt = new SQLCreateFunctionStatement(); stmt.setDbType(dbType); - if (lexer.token() != Token.FUNCTION) { - if (lexer.identifierEquals("DEFINER")) { + if (lexer.token() == Token.CREATE) { + lexer.nextToken(); + + if (lexer.token() == Token.OR) { lexer.nextToken(); - accept(Token.EQ); - SQLName definer = this.exprParser.name(); - stmt.setDefiner(definer); - } else { - accept(Token.CREATE); - if (lexer.token() == Token.OR) { - lexer.nextToken(); - accept(Token.REPLACE); - stmt.setOrReplace(true); - } + accept(Token.REPLACE); + stmt.setOrReplace(true); } } + if (lexer.identifierEquals(FnvHash.Constants.DEFINER)) { + lexer.nextToken(); + accept(Token.EQ); + SQLName definer = this.getExprParser().userName(); + stmt.setDefiner(definer); + } + accept(Token.FUNCTION); stmt.setName(this.exprParser.name()); diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java index 397d0a173c..5e4ecfdce3 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java @@ -2428,6 +2428,16 @@ public class SQLExprParser extends SQLParser { accept(Token.SET); + if (lexer.token != Token.IDENTIFIER + && lexer.token != Token.LITERAL_CHARS + && lexer.token != Token.BINARY) { + throw new ParserException(lexer.info()); + } + charType.setCharSetName(lexer.stringVal()); + lexer.nextToken(); + } else if (lexer.identifierEquals(FnvHash.Constants.CHARSET)) { + lexer.nextToken(); + if (lexer.token != Token.IDENTIFIER && lexer.token != Token.LITERAL_CHARS && lexer.token != Token.BINARY) { 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 b52c330747..08d74551ca 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java @@ -600,8 +600,10 @@ public class SQLStatementParser extends SQLParser { stmt.setExpr(expr); } - accept(Token.SEMI); - stmt.setAfterSemi(true); + if (lexer.token == Token.SEMI) { + lexer.nextToken(); + stmt.setAfterSemi(true); + } return stmt; } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/create_function/MySql_Create_Function_1.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/create_function/MySql_Create_Function_1.java new file mode 100644 index 0000000000..2a0857c7a8 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/create_function/MySql_Create_Function_1.java @@ -0,0 +1,69 @@ +/* + * 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.create_function; + +import com.alibaba.druid.sql.MysqlTest; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.visitor.SchemaStatVisitor; +import com.alibaba.druid.util.JdbcConstants; + +import java.util.List; + +public class MySql_Create_Function_1 extends MysqlTest { + + public void test_0() throws Exception { + String sql = "CREATE DEFINER=`root`@`%` FUNCTION `hello`(s CHAR(20)) RETURNS char(50) CHARSET big5\n" + + " DETERMINISTIC\n" + + "RETURN CONCAT('Hello, ',s,'!')"; + + List statementList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL); + SQLStatement stmt = statementList.get(0); + + assertEquals(1, statementList.size()); + + SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.MYSQL); + stmt.accept(visitor); + + assertEquals("CREATE FUNCTION `hello` (\n" + + "\ts CHAR(20)\n" + + ")\n" + + "RETURNS char(50) CHARACTER SET big5 DETERMINISTIC\n" + + "RETURN CONCAT('Hello, ', s, '!')", // + SQLUtils.toMySqlString(stmt)); + + assertEquals("create function `hello` (\n" + + "\ts CHAR(20)\n" + + ")\n" + + "returns char(50) character set big5 deterministic\n" + + "return CONCAT('Hello, ', s, '!')", // + SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION)); + +// System.out.println("Tables : " + visitor.getTables()); +// System.out.println("fields : " + visitor.getColumns()); +// System.out.println("coditions : " + visitor.getConditions()); +// System.out.println("orderBy : " + visitor.getOrderByColumns()); + + assertEquals(0, visitor.getTables().size()); + assertEquals(1, visitor.getColumns().size()); + assertEquals(0, visitor.getConditions().size()); + +// Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("City"))); +// Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("t2"))); + +// Assert.assertTrue(visitor.getColumns().contains(new Column("t2", "id"))); + } +}