diff --git a/src/main/java/com/alibaba/druid/sql/ast/SQLObjectImpl.java b/src/main/java/com/alibaba/druid/sql/ast/SQLObjectImpl.java index ab82d501d7..2f27b7acbd 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/SQLObjectImpl.java +++ b/src/main/java/com/alibaba/druid/sql/ast/SQLObjectImpl.java @@ -24,9 +24,9 @@ import com.alibaba.druid.sql.visitor.SQLASTVisitor; public abstract class SQLObjectImpl implements SQLObject { - private SQLObject parent; + private SQLObject parent; - private Map attributes; + protected Map attributes; public SQLObjectImpl(){ } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateTableStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateTableStatement.java index 7359f68fc8..f83b80f90d 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateTableStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateTableStatement.java @@ -16,6 +16,7 @@ package com.alibaba.druid.sql.ast.statement; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import com.alibaba.druid.sql.ast.SQLName; @@ -119,4 +120,37 @@ public class SQLCreateTableStatement extends SQLStatementImpl implements SQLDDLS } visitor.endVisit(this); } + + @SuppressWarnings("unchecked") + public void addBodyBeforeComment(List comments) { + if (attributes == null) { + attributes = new HashMap(1); + } + + List attrComments = (List) attributes.get("format.body_before_comment"); + if (attrComments == null) { + attributes.put("format.body_before_comment", comments); + } else { + attrComments.addAll(comments); + } + } + + @SuppressWarnings("unchecked") + public List getBodyBeforeCommentsDirect() { + if (attributes == null) { + return null; + } + + return (List) attributes.get("format.body_before_comment"); + } + + public boolean hasBodyBeforeComment() { + List comments = getBodyBeforeCommentsDirect(); + if (comments == null) { + return false; + } + + return !comments.isEmpty(); + } + } 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 38990cd5df..73809c8b34 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 @@ -22,7 +22,6 @@ import static com.alibaba.druid.sql.parser.Token.LITERAL_CHARS; import java.util.HashMap; import java.util.Map; -import com.alibaba.druid.sql.parser.CharTypes; import com.alibaba.druid.sql.parser.Keywords; import com.alibaba.druid.sql.parser.Lexer; import com.alibaba.druid.sql.parser.NotAllowCommentException; @@ -512,9 +511,28 @@ public class MySqlLexer extends Lexer { return; } } + + private final static boolean[] identifierFlags = new boolean[256]; + static { + for (char c = 0; c < identifierFlags.length; ++c) { + if (c >= 'A' && c <= 'Z') { + identifierFlags[c] = true; + } else if (c >= 'a' && c <= 'z') { + identifierFlags[c] = true; + } else if (c >= '0' && c <= '9') { + identifierFlags[c] = true; + } + } + // identifierFlags['`'] = true; + identifierFlags['_'] = true; + identifierFlags['-'] = true; // mysql + } - private boolean isIdentifierChar(char c) { - return c != '#' && CharTypes.isIdentifierChar(c); + public static boolean isIdentifierChar(char c) { + if (c <= identifierFlags.length) { + return identifierFlags[c]; + } + return false; } public void scanNumber() { diff --git a/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsCreateTableParser.java b/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsCreateTableParser.java index aab2945637..fdaf11531a 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsCreateTableParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsCreateTableParser.java @@ -73,6 +73,10 @@ public class OdpsCreateTableParser extends SQLCreateTableParser { } else { accept(Token.LPAREN); + if (lexer.isKeepComments() && lexer.hasComment()) { + stmt.addBodyBeforeComment(lexer.readAndResetComments()); + } + for (;;) { if (lexer.token() != Token.IDENTIFIER) { throw new ParserException("expect identifier"); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/odps/visitor/OdpsOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/odps/visitor/OdpsOutputVisitor.java index 82a3f55760..29a1358653 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/odps/visitor/OdpsOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/odps/visitor/OdpsOutputVisitor.java @@ -96,6 +96,12 @@ public class OdpsOutputVisitor extends SQLASTOutputVisitor implements OdpsASTVis int size = x.getTableElementList().size(); if (size > 0) { print0(" ("); + + if (this.isPrettyFormat() && x.hasBodyBeforeComment()) { + print(' '); + printComment(x.getBodyBeforeCommentsDirect(), ""); + } + incrementIndent(); println(); for (int i = 0; i < size; ++i) { diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlShowTest_table2.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlShowTest_table2.java new file mode 100644 index 0000000000..abb29074cc --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlShowTest_table2.java @@ -0,0 +1,48 @@ +/* + * Copyright 1999-2101 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 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.dialect.mysql.parser.MySqlStatementParser; +import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor; + +public class MySqlShowTest_table2 extends MysqlTest { + + public void test_0() throws Exception { + String sql = "SHOW FULL TABLES FROM test-db WHERE Table_type != 'VIEW'"; + + MySqlStatementParser parser = new MySqlStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement stmt = statementList.get(0); + + Assert.assertEquals(1, statementList.size()); + + MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor(); + stmt.accept(visitor); + + Assert.assertEquals(0, visitor.getTables().size()); + Assert.assertEquals(0, visitor.getColumns().size()); + Assert.assertEquals(0, visitor.getConditions().size()); + Assert.assertEquals(0, visitor.getOrderByColumns().size()); + + // Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("mytable"))); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsFormatCommentTest29.java b/src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsFormatCommentTest29.java new file mode 100644 index 0000000000..ca61a5c7d1 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsFormatCommentTest29.java @@ -0,0 +1,20 @@ +package com.alibaba.druid.bvt.sql.odps; + +import org.junit.Assert; + +import com.alibaba.druid.sql.SQLUtils; + +import junit.framework.TestCase; + +public class OdpsFormatCommentTest29 extends TestCase { + public void test_drop_function() throws Exception { + String sql = "create table xxxx001( --测试" + + "\ncol string, --测试2" + + "\ncol2 string --测试3" + + "\n)"; + Assert.assertEquals("CREATE TABLE xxxx001 ( --测试" + + "\n\tcol STRING, --测试2" + + "\n\tcol2 STRING --测试3" + + "\n)", SQLUtils.formatOdps(sql)); + } +}