From 74a27a4b7f74497faf07a1edcfa78e0de5294ce4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B8=A9=E5=B0=91?= Date: Fri, 18 May 2012 10:35:42 +0800 Subject: [PATCH] mysql parser --- .../dialect/mysql/parser/MySqlExprParser.java | 11 +++ .../sql/dialect/mysql/parser/MySqlLexer.java | 92 +++++++++++++++++++ .../sql/dialect/oracle/ast/OracleHint.java | 14 +-- .../oracle/visitor/OracleOutputVisitor.java | 2 +- .../druid/bvt/sql/cobar/HintsTest.java | 22 +++++ 5 files changed, 133 insertions(+), 8 deletions(-) create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/cobar/HintsTest.java diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java index 1af8b3f70d..1f170f2684 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java @@ -15,7 +15,10 @@ */ package com.alibaba.druid.sql.dialect.mysql.parser; +import java.util.List; + import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.ast.SQLHint; import com.alibaba.druid.sql.ast.SQLName; import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr; import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator; @@ -40,6 +43,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlUserName; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSQLColumnDefinition; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock.Limit; +import com.alibaba.druid.sql.dialect.oracle.ast.OracleHint; import com.alibaba.druid.sql.parser.Lexer; import com.alibaba.druid.sql.parser.ParserException; import com.alibaba.druid.sql.parser.SQLExprParser; @@ -606,4 +610,11 @@ public class MySqlExprParser extends SQLExprParser { return null; } + + public void parseHints(List hints) { + if (lexer.token() == Token.HINT) { + hints.add(new OracleHint(lexer.stringVal())); + lexer.nextToken(); + } + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlLexer.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlLexer.java index 26c8325019..b9f218a543 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlLexer.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlLexer.java @@ -25,6 +25,7 @@ import java.util.Map; import com.alibaba.druid.sql.parser.Keywords; import com.alibaba.druid.sql.parser.Lexer; +import com.alibaba.druid.sql.parser.NotAllowCommentException; import com.alibaba.druid.sql.parser.SQLParseException; import com.alibaba.druid.sql.parser.Token; @@ -347,4 +348,95 @@ public class MySqlLexer extends Lexer { stringVal = new String(sbuf, 0, sp); } } + + public void scanComment() { + if (ch != '/' && ch != '-') { + throw new IllegalStateException(); + } + + np = bp; + sp = 0; + scanChar(); + + // /*+ */ + if (ch == '*') { + scanChar(); + sp++; + + while (ch == ' ') { + scanChar(); + sp++; + } + + boolean isHint = false; + int startHintSp = sp + 1; + if (ch == '!') { + isHint = true; + scanChar(); + sp++; + } + + for (;;) { + if (ch == '*' && buf[bp + 1] == '/') { + sp += 2; + scanChar(); + scanChar(); + break; + } + + scanChar(); + sp++; + } + + if (isHint) { + stringVal = new String(buf, np + startHintSp, (sp - startHintSp) - 2).trim(); + token = Token.HINT; + } else { + stringVal = new String(buf, np, sp); + token = Token.MULTI_LINE_COMMENT; + } + + if (token != Token.HINT && !isAllowComment()) { + throw new NotAllowCommentException(); + } + + return; + } + + if (!isAllowComment()) { + throw new NotAllowCommentException(); + } + + if (ch == '/' || ch == '-') { + scanChar(); + sp++; + + for (;;) { + if (ch == '\r') { + if (buf[bp + 1] == '\n') { + sp += 2; + scanChar(); + break; + } + sp++; + break; + } else if (ch == EOI) { + break; + } + + if (ch == '\n') { + scanChar(); + sp++; + break; + } + + scanChar(); + sp++; + } + + stringVal = new String(buf, np + 1, sp); + token = Token.LINE_COMMENT; + return; + } + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/OracleHint.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/OracleHint.java index 1ffc5606c4..99b96bf490 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/OracleHint.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/OracleHint.java @@ -22,23 +22,23 @@ public class OracleHint extends OracleSQLObjectImpl implements SQLHint { private static final long serialVersionUID = 1L; - private String name; + private String text; public OracleHint(){ } - public OracleHint(String name){ + public OracleHint(String text){ - this.name = name; + this.text = text; } - public String getName() { - return this.name; + public String getText() { + return this.text; } - public void setName(String name) { - this.name = name; + public void setText(String text) { + this.text = text; } public void accept0(OracleASTVisitor visitor) { diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java index 3db6ef8126..7f692a2e53 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java @@ -321,7 +321,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS } public boolean visit(OracleHint x) { - print(x.getName()); + print(x.getText()); return false; } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/cobar/HintsTest.java b/src/test/java/com/alibaba/druid/bvt/sql/cobar/HintsTest.java new file mode 100644 index 0000000000..96fd534653 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/cobar/HintsTest.java @@ -0,0 +1,22 @@ +package com.alibaba.druid.bvt.sql.cobar; + +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; + +import junit.framework.TestCase; + + +public class HintsTest extends TestCase { + public void test_hints_0() throws Exception { + String sql = "CREATE /*!32302 TEMPORARY */ TABLE t (a INT);"; + MySqlStatementParser parser = new MySqlStatementParser(sql); + SQLStatement stmt = parser.parseStatementList().get(0); + parser.match(Token.EOF); + String output = SQLUtils.toMySqlString(stmt); + Assert.assertEquals("CREATE TABLE t (\n\ta INT\n)", output); + } +}