From 60b7139911411e1f92882f1297c22c22ba3d8bd5 Mon Sep 17 00:00:00 2001 From: "shaojin.wensj" Date: Fri, 10 Jul 2015 14:47:01 +0800 Subject: [PATCH 1/2] improved sql parser for odps show tables --- .../ast/statement/SQLShowTablesStatement.java | 44 +++++++++++++++++++ .../ast/statement/MySqlShowStatement.java | 2 +- .../statement/MySqlShowTablesStatement.java | 32 +++++--------- .../odps/parser/OdpsStatementParser.java | 21 +++++++++ .../druid/sql/parser/SQLStatementParser.java | 2 +- .../sql/visitor/SQLASTOutputVisitor.java | 16 +++++++ .../druid/sql/visitor/SQLASTVisitor.java | 5 +++ .../sql/visitor/SQLASTVisitorAdapter.java | 11 +++++ .../bvt/sql/odps/OdpsShowTablesTest0.java | 40 +++++++++++++++++ 9 files changed, 151 insertions(+), 22 deletions(-) create mode 100644 src/main/java/com/alibaba/druid/sql/ast/statement/SQLShowTablesStatement.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsShowTablesTest0.java diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLShowTablesStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLShowTablesStatement.java new file mode 100644 index 0000000000..9af85c89bb --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLShowTablesStatement.java @@ -0,0 +1,44 @@ +package com.alibaba.druid.sql.ast.statement; + +import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.ast.SQLName; +import com.alibaba.druid.sql.ast.SQLStatementImpl; +import com.alibaba.druid.sql.visitor.SQLASTVisitor; + +public class SQLShowTablesStatement extends SQLStatementImpl { + + protected SQLName database; + protected SQLExpr like; + + public SQLName getDatabase() { + return database; + } + + public void setDatabase(SQLName database) { + if (database != null) { + database.setParent(this); + } + + this.database = database; + } + + public SQLExpr getLike() { + return like; + } + + public void setLike(SQLExpr like) { + if (like != null) { + like.setParent(this); + } + + this.like = like; + } + + @Override + protected void accept0(SQLASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, database); + acceptChild(visitor, like); + } + } +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowStatement.java index 8989fe4a93..275160a6df 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowStatement.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowStatement.java @@ -15,6 +15,6 @@ */ package com.alibaba.druid.sql.dialect.mysql.ast.statement; -public interface MySqlShowStatement { +public interface MySqlShowStatement extends MySqlStatement { } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowTablesStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowTablesStatement.java index 2f90640c77..4888a7d6cf 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowTablesStatement.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlShowTablesStatement.java @@ -16,15 +16,14 @@ package com.alibaba.druid.sql.dialect.mysql.ast.statement; import com.alibaba.druid.sql.ast.SQLExpr; -import com.alibaba.druid.sql.ast.SQLName; +import com.alibaba.druid.sql.ast.statement.SQLShowTablesStatement; import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor; +import com.alibaba.druid.sql.visitor.SQLASTVisitor; -public class MySqlShowTablesStatement extends MySqlStatementImpl implements MySqlShowStatement { +public class MySqlShowTablesStatement extends SQLShowTablesStatement implements MySqlShowStatement { private boolean full; - private SQLName database; - private SQLExpr like; private SQLExpr where; public boolean isFull() { @@ -35,22 +34,6 @@ public class MySqlShowTablesStatement extends MySqlStatementImpl implements MySq this.full = full; } - public SQLName getDatabase() { - return database; - } - - public void setDatabase(SQLName database) { - this.database = database; - } - - public SQLExpr getLike() { - return like; - } - - public void setLike(SQLExpr like) { - this.like = like; - } - public SQLExpr getWhere() { return where; } @@ -67,4 +50,13 @@ public class MySqlShowTablesStatement extends MySqlStatementImpl implements MySq } visitor.endVisit(this); } + + @Override + protected void accept0(SQLASTVisitor visitor) { + if (visitor instanceof MySqlASTVisitor) { + accept0((MySqlASTVisitor) visitor); + } else { + throw new IllegalArgumentException("not support visitor type : " + visitor.getClass().getName()); + } + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsStatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsStatementParser.java index b477de0075..01541245b2 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsStatementParser.java @@ -26,6 +26,7 @@ import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; import com.alibaba.druid.sql.ast.statement.SQLSelect; import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; import com.alibaba.druid.sql.ast.statement.SQLSetStatement; +import com.alibaba.druid.sql.ast.statement.SQLShowTablesStatement; import com.alibaba.druid.sql.ast.statement.SQLSubqueryTableSource; import com.alibaba.druid.sql.dialect.odps.ast.OdpsInsert; import com.alibaba.druid.sql.dialect.odps.ast.OdpsInsertStatement; @@ -172,6 +173,25 @@ public class OdpsStatementParser extends SQLStatementParser { return stmt; } + + if (identifierEquals("TABLES")) { + lexer.nextToken(); + + SQLShowTablesStatement stmt = new SQLShowTablesStatement(); + + if (lexer.token() == Token.FROM) { + lexer.nextToken(); + stmt.setDatabase(this.exprParser.name()); + } + + if (lexer.token() == Token.LIKE) { + lexer.nextToken(); + stmt.setLike(this.exprParser.expr()); + } + + return stmt; + } + throw new ParserException("TODO " + lexer.token() + " " + lexer.stringVal()); } @@ -211,4 +231,5 @@ public class OdpsStatementParser extends SQLStatementParser { } } + } 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 7ecf1eb47a..831e722208 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java @@ -354,7 +354,7 @@ public class SQLStatementParser extends SQLParser { public SQLStatement parseShow() { throw new ParserException("TODO " + lexer.token() + " " + lexer.stringVal()); } - + public SQLUseStatement parseUse() { accept(Token.USE); SQLUseStatement stmt = new SQLUseStatement(getDbType()); diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java index 3644c6bf4b..94b4121534 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -136,6 +136,7 @@ import com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem; import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; import com.alibaba.druid.sql.ast.statement.SQLSetStatement; +import com.alibaba.druid.sql.ast.statement.SQLShowTablesStatement; import com.alibaba.druid.sql.ast.statement.SQLSubqueryTableSource; import com.alibaba.druid.sql.ast.statement.SQLTableElement; import com.alibaba.druid.sql.ast.statement.SQLTruncateStatement; @@ -2166,4 +2167,19 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Printab x.getTo().accept(this); return false; } + + @Override + public boolean visit(SQLShowTablesStatement x) { + print("SHOW TABLES"); + if (x.getDatabase() != null) { + print(" FROM "); + x.getDatabase().accept(this); + } + + if (x.getLike() != null) { + print(" LIKE "); + x.getLike().accept(this); + } + return false; + } } diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java index 0a15b8f3ef..ab0b3fe040 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java @@ -113,6 +113,7 @@ import com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem; import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; import com.alibaba.druid.sql.ast.statement.SQLSetStatement; +import com.alibaba.druid.sql.ast.statement.SQLShowTablesStatement; import com.alibaba.druid.sql.ast.statement.SQLSubqueryTableSource; import com.alibaba.druid.sql.ast.statement.SQLTruncateStatement; import com.alibaba.druid.sql.ast.statement.SQLUnionQuery; @@ -569,4 +570,8 @@ public interface SQLASTVisitor { boolean visit(SQLAlterTableRename x); + void endVisit(SQLShowTablesStatement x); + + boolean visit(SQLShowTablesStatement x); + } diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java index c6741084c1..77c3b3d1c8 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java @@ -115,6 +115,7 @@ import com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem; import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; import com.alibaba.druid.sql.ast.statement.SQLSetStatement; +import com.alibaba.druid.sql.ast.statement.SQLShowTablesStatement; import com.alibaba.druid.sql.ast.statement.SQLSubqueryTableSource; import com.alibaba.druid.sql.ast.statement.SQLTruncateStatement; import com.alibaba.druid.sql.ast.statement.SQLUnionQuery; @@ -1115,4 +1116,14 @@ public class SQLASTVisitorAdapter implements SQLASTVisitor { return true; } + @Override + public void endVisit(SQLShowTablesStatement x) { + + } + + @Override + public boolean visit(SQLShowTablesStatement x) { + return true; + } + } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsShowTablesTest0.java b/src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsShowTablesTest0.java new file mode 100644 index 0000000000..fcf425f9ec --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsShowTablesTest0.java @@ -0,0 +1,40 @@ +package com.alibaba.druid.bvt.sql.odps; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.odps.parser.OdpsStatementParser; +import com.alibaba.druid.sql.parser.Token; + +public class OdpsShowTablesTest0 extends TestCase { + + public void test_0() throws Exception { + String sql = "show tables"; + OdpsStatementParser parser = new OdpsStatementParser(sql); + SQLStatement stmt = parser.parseStatementList().get(0); + parser.match(Token.EOF); + String output = SQLUtils.toOdpsString(stmt); + Assert.assertEquals("SHOW TABLES", output); + } + + public void test_from() throws Exception { + String sql = "show tables from xx"; + OdpsStatementParser parser = new OdpsStatementParser(sql); + SQLStatement stmt = parser.parseStatementList().get(0); + parser.match(Token.EOF); + String output = SQLUtils.toOdpsString(stmt); + Assert.assertEquals("SHOW TABLES FROM xx", output); + } + + public void test_from_like() throws Exception { + String sql = "show tables from xx like '*'"; + OdpsStatementParser parser = new OdpsStatementParser(sql); + SQLStatement stmt = parser.parseStatementList().get(0); + parser.match(Token.EOF); + String output = SQLUtils.toOdpsString(stmt); + Assert.assertEquals("SHOW TABLES FROM xx LIKE '*'", output); + } +} From b36374f7bf35dd75eeb58c9aacf42cb2d6a7f0fa Mon Sep 17 00:00:00 2001 From: "shaojin.wensj" Date: Sat, 11 Jul 2015 14:27:29 +0800 Subject: [PATCH 2/2] improved sql format output --- .../java/com/alibaba/druid/sql/SQLUtils.java | 26 ++++++- .../com/alibaba/druid/sql/ast/SQLObject.java | 13 ++++ .../alibaba/druid/sql/ast/SQLObjectImpl.java | 67 +++++++++++++++++ .../sql/dialect/mysql/parser/MySqlLexer.java | 17 +++-- .../dialect/odps/parser/OdpsExprParser.java | 13 +++- .../sql/dialect/odps/parser/OdpsLexer.java | 26 ++++++- .../dialect/odps/parser/OdpsSelectParser.java | 8 ++- .../odps/parser/OdpsStatementParser.java | 11 ++- .../odps/visitor/OdpsOutputVisitor.java | 27 ++++++- .../dialect/oracle/parser/OracleLexer.java | 6 ++ .../sqlserver/parser/SQLServerLexer.java | 6 ++ .../com/alibaba/druid/sql/parser/Lexer.java | 53 +++++++++++++- .../druid/sql/parser/SQLExprParser.java | 11 ++- .../druid/sql/parser/SQLSelectParser.java | 26 +++++-- .../druid/sql/parser/SQLStatementParser.java | 72 +++++++++++++++++-- .../ParameterizedOutputVisitorUtils.java | 2 +- .../sql/visitor/SQLASTOutputVisitor.java | 27 ++++++- .../druid/bvt/sql/mysql/MySqlFormatTest.java | 3 +- .../bvt/sql/odps/OdpsFormatCommentTest.java | 34 +++++++++ .../bvt/sql/odps/OdpsFormatCommentTest2.java | 27 +++++++ .../bvt/sql/odps/OdpsFormatCommentTest3.java | 30 ++++++++ .../bvt/sql/odps/OdpsFormatCommentTest4.java | 40 +++++++++++ .../bvt/sql/odps/OdpsFormatCommentTest5.java | 48 +++++++++++++ .../bvt/sql/odps/OdpsFormatCommentTest6.java | 25 +++++++ .../druid/bvt/sql/odps/OdpsFormatTest.java | 26 +++++++ .../bvt/sql/postgresql/PGFormatTest.java | 3 +- 26 files changed, 612 insertions(+), 35 deletions(-) create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsFormatCommentTest.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsFormatCommentTest2.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsFormatCommentTest3.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsFormatCommentTest4.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsFormatCommentTest5.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsFormatCommentTest6.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsFormatTest.java diff --git a/src/main/java/com/alibaba/druid/sql/SQLUtils.java b/src/main/java/com/alibaba/druid/sql/SQLUtils.java index 68acc9f166..59087e1601 100644 --- a/src/main/java/com/alibaba/druid/sql/SQLUtils.java +++ b/src/main/java/com/alibaba/druid/sql/SQLUtils.java @@ -226,7 +226,10 @@ public class SQLUtils { public static String format(String sql, String dbType, List parameters) { try { - List statementList = toStatementList(sql, dbType); + SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType); + parser.setKeepComments(true); + + List statementList = parser.parseStatementList(); return toSQLString(statementList, dbType, parameters); } catch (ParserException ex) { @@ -247,10 +250,27 @@ public class SQLUtils { } for (int i = 0; i < statementList.size(); i++) { + SQLStatement stmt = statementList.get(i); + if (i > 0) { - out.append(";\n"); + visitor.println(";"); + } + + List comments = stmt.getBeforeCommentsDirect(); + if (comments != null){ + for(String comment : comments) { + visitor.println(comment); + } + } + stmt.accept(visitor); + + if (i == statementList.size() - 1) { + Boolean semi = (Boolean) stmt.getAttribute("format.semi"); + if (semi != null && semi.booleanValue()) { + visitor.println(); + visitor.print(";"); + } } - statementList.get(i).accept(visitor); } return out.toString(); diff --git a/src/main/java/com/alibaba/druid/sql/ast/SQLObject.java b/src/main/java/com/alibaba/druid/sql/ast/SQLObject.java index 9bc3f824e5..99bd8e38fa 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/SQLObject.java +++ b/src/main/java/com/alibaba/druid/sql/ast/SQLObject.java @@ -15,6 +15,7 @@ */ package com.alibaba.druid.sql.ast; +import java.util.List; import java.util.Map; import com.alibaba.druid.sql.visitor.SQLASTVisitor; @@ -34,6 +35,18 @@ public interface SQLObject { void putAttribute(String name, Object value); Map getAttributesDirect(); + + void addBeforeComment(String comment); + + List getBeforeCommentsDirect(); + + void addAfterComment(String comment); + + List getAfterCommentsDirect(); + + boolean hasBeforeComment(); + + boolean hasAfterComment() void output(StringBuffer buf); } 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 82dc0a69d5..4094fed083 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/SQLObjectImpl.java +++ b/src/main/java/com/alibaba/druid/sql/ast/SQLObjectImpl.java @@ -15,6 +15,7 @@ */ package com.alibaba.druid.sql.ast; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -107,4 +108,70 @@ public abstract class SQLObjectImpl implements SQLObject { public Map getAttributesDirect() { return attributes; } + + @SuppressWarnings("unchecked") + public void addBeforeComment(String comment) { + if (attributes == null) { + attributes = new HashMap(1); + } + + List comments = (List) attributes.get("format.before_comment"); + if (comments == null) { + comments = new ArrayList(2); + attributes.put("format.before_comment", comments); + } + + comments.add(comment); + } + + @SuppressWarnings("unchecked") + public List getBeforeCommentsDirect() { + if (attributes == null) { + return null; + } + + return (List) attributes.get("format.before_comment"); + } + + @SuppressWarnings("unchecked") + public void addAfterComment(String comment) { + if (attributes == null) { + attributes = new HashMap(1); + } + + List comments = (List) attributes.get("format.after_comment"); + if (comments == null) { + comments = new ArrayList(2); + attributes.put("format.after_comment", comments); + } + + comments.add(comment); + } + + @SuppressWarnings("unchecked") + public List getAfterCommentsDirect() { + if (attributes == null) { + return null; + } + + return (List) attributes.get("format.after_comment"); + } + + public boolean hasBeforeComment() { + List comments = getBeforeCommentsDirect(); + if (comments == null) { + return false; + } + + return !comments.isEmpty(); + } + + public boolean hasAfterComment() { + List comments = getAfterCommentsDirect(); + 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 d38b9b0f87..e533050701 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 @@ -109,6 +109,9 @@ public class MySqlLexer extends Lexer { stringVal = subString(mark, bufPos); token = Token.LINE_COMMENT; hasComment = true; + if (keepComments) { + commentVal = stringVal; + } if (commentHandler != null && commentHandler.handle(lastToken, stringVal)) { return; @@ -448,13 +451,16 @@ public class MySqlLexer extends Lexer { stringVal = subString(mark, bufPos); token = Token.MULTI_LINE_COMMENT; hasComment = true; - } - - if (commentHandler != null && commentHandler.handle(lastToken, stringVal)) { - return; + if (keepComments) { + commentVal = stringVal; + } } endOfComment = isEOF(); + + if (commentHandler != null && commentHandler.handle(lastToken, stringVal)) { + return; + } if (!isHint && !isAllowComment() && !isSafeComment(stringVal)) { throw new NotAllowCommentException(); @@ -492,6 +498,9 @@ public class MySqlLexer extends Lexer { stringVal = subString(mark, bufPos + 1); token = Token.LINE_COMMENT; hasComment = true; + if (keepComments) { + commentVal = stringVal; + } if (commentHandler != null && commentHandler.handle(lastToken, stringVal)) { return; diff --git a/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsExprParser.java b/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsExprParser.java index d6bc801569..4f679bcaf1 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsExprParser.java @@ -48,6 +48,11 @@ public class OdpsExprParser extends SQLExprParser { this.lexer.nextToken(); } + public OdpsExprParser(String sql, Lexer.CommentHandler commentHandler){ + this(new OdpsLexer(sql, commentHandler)); + this.lexer.nextToken(); + } + protected SQLExpr parseAliasExpr(String alias) { return new SQLCharExpr(alias); } @@ -97,7 +102,13 @@ public class OdpsExprParser extends SQLExprParser { } final String alias = as(); + + SQLSelectItem item = new SQLSelectItem(expr, alias); + + if (lexer.hasComment() && lexer.isKeepComments()) { + item.addAfterComment(lexer.commentVal()); + } - return new SQLSelectItem(expr, alias); + return item; } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsLexer.java b/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsLexer.java index 0de4ee60af..d2ed2fa8a3 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsLexer.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsLexer.java @@ -52,10 +52,17 @@ public class OdpsLexer extends Lexer { super.keywods = DEFAULT_ODPS_KEYWORDS; } + public OdpsLexer(String input, CommentHandler commentHandler){ + super(input, commentHandler); + super.keywods = DEFAULT_ODPS_KEYWORDS; + } + public void scanComment() { if (ch != '/' && ch != '-') { throw new IllegalStateException(); } + + Token lastToken = this.token; mark = pos; bufPos = 0; @@ -95,9 +102,16 @@ public class OdpsLexer extends Lexer { stringVal = subString(mark + startHintSp, (bufPos - startHintSp) - 1); token = Token.HINT; } else { - stringVal = subString(mark, bufPos); + stringVal = subString(mark, bufPos + 1); token = Token.MULTI_LINE_COMMENT; hasComment = true; + if (keepComments) { + commentVal = stringVal; + } + } + + if (commentHandler != null && commentHandler.handle(lastToken, stringVal)) { + return; } if (token != Token.HINT && !isAllowComment()) { @@ -138,10 +152,18 @@ public class OdpsLexer extends Lexer { bufPos++; } - stringVal = subString(mark + 1, bufPos); + stringVal = subString(mark, bufPos); token = Token.LINE_COMMENT; hasComment = true; + if (keepComments) { + commentVal = stringVal; + } endOfComment = isEOF(); + + if (commentHandler != null && commentHandler.handle(lastToken, stringVal)) { + return; + } + return; } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsSelectParser.java b/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsSelectParser.java index 26ecd1a7a3..ab5a222dec 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsSelectParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsSelectParser.java @@ -40,14 +40,18 @@ public class OdpsSelectParser extends SQLSelectParser { return queryRest(select); } + OdpsSelectQueryBlock queryBlock = new OdpsSelectQueryBlock(); + + if (lexer.hasComment() && lexer.isKeepComments()) { + queryBlock.addBeforeComment(lexer.commentVal()); + } + accept(Token.SELECT); if (lexer.token() == Token.COMMENT) { lexer.nextToken(); } - OdpsSelectQueryBlock queryBlock = new OdpsSelectQueryBlock(); - if (lexer.token() == Token.DISTINCT) { queryBlock.setDistionOption(SQLSetQuantifier.DISTINCT); lexer.nextToken(); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsStatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsStatementParser.java index 01541245b2..42d8251e4a 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsStatementParser.java @@ -42,9 +42,11 @@ import com.alibaba.druid.sql.parser.Token; import com.alibaba.druid.util.JdbcConstants; public class OdpsStatementParser extends SQLStatementParser { - public OdpsStatementParser(String sql){ - super(new OdpsExprParser(sql)); + super (new OdpsLexer(sql), JdbcConstants.ODPS); + this.exprParser = new OdpsExprParser(this.lexer); + this.lexer.setCommentHandler(commentCallBack); + this.lexer.nextToken(); } public OdpsStatementParser(SQLExprParser exprParser){ @@ -108,6 +110,11 @@ public class OdpsStatementParser extends SQLStatementParser { public OdpsInsert parseOdpsInsert() { OdpsInsert insert = new OdpsInsert(); + + if (lexer.hasComment()) { + insert.addBeforeComment(lexer.commentVal()); + } + SQLSelectParser selectParser = createSQLSelectParser(); accept(Token.INSERT); 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 afde1c53bb..e36c39dd94 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 @@ -153,6 +153,10 @@ public class OdpsOutputVisitor extends SQLASTOutputVisitor implements OdpsASTVis @Override public boolean visit(OdpsInsert x) { + if (x.hasBeforeComment()) { + printComment(x.getBeforeCommentsDirect(), "\n"); + println(); + } if (x.isOverwrite()) { print("INSERT OVERWRITE TABLE "); } else { @@ -231,12 +235,22 @@ public class OdpsOutputVisitor extends SQLASTOutputVisitor implements OdpsASTVis protected void printSelectList(List selectList) { incrementIndent(); for (int i = 0, size = selectList.size(); i < size; ++i) { + SQLSelectItem selectItem = selectList.get(i); + if (i != 0) { print(", "); + + printComment(selectList.get(i - 1).getAfterCommentsDirect(), "\n"); + println(); } - - selectList.get(i).accept(this); + + selectItem.accept(this); + + if (i == selectList.size() - 1 && selectItem.hasAfterComment()) { + print(' '); + printComment(selectItem.getAfterCommentsDirect(), "\n"); + } } decrementIndent(); } @@ -374,6 +388,11 @@ public class OdpsOutputVisitor extends SQLASTOutputVisitor implements OdpsASTVis @Override public boolean visit(OdpsSelectQueryBlock x) { + if (isPrettyFormat() && x.hasBeforeComment()) { + printComment(x.getBeforeCommentsDirect(), "\n"); + println(); + } + print("SELECT "); if (SQLSetQuantifier.ALL == x.getDistionOption()) { @@ -397,6 +416,10 @@ public class OdpsOutputVisitor extends SQLASTOutputVisitor implements OdpsASTVis print("WHERE "); x.getWhere().setParent(x); x.getWhere().accept(this); + if (x.getWhere().hasAfterComment() && isPrettyFormat()) { + print(' '); + printComment(x.getWhere().getAfterCommentsDirect(), "\n"); + } } if (x.getGroupBy() != null) { diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleLexer.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleLexer.java index 54d6687966..3a982bd9ad 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleLexer.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleLexer.java @@ -231,6 +231,9 @@ public class OracleLexer extends Lexer { stringVal = subString(mark, bufPos); token = Token.MULTI_LINE_COMMENT; hasComment = true; + if (keepComments) { + commentVal = stringVal; + } } if (token != Token.HINT && !isAllowComment()) { @@ -274,6 +277,9 @@ public class OracleLexer extends Lexer { stringVal = subString(mark + 1, bufPos); token = Token.LINE_COMMENT; hasComment = true; + if (keepComments) { + commentVal = stringVal; + } endOfComment = isEOF(); return; } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerLexer.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerLexer.java index 0f50a6fc91..3732551a40 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerLexer.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerLexer.java @@ -106,6 +106,9 @@ public class SQLServerLexer extends Lexer { stringVal = subString(mark, bufPos); token = Token.MULTI_LINE_COMMENT; hasComment = true; + if (keepComments) { + commentVal = stringVal; + } } if (token != Token.HINT && !isAllowComment() && !isSafeComment(stringVal)) { @@ -145,6 +148,9 @@ public class SQLServerLexer extends Lexer { stringVal = subString(mark + 1, bufPos); token = Token.LINE_COMMENT; hasComment = true; + if (keepComments) { + commentVal = stringVal; + } endOfComment = isEOF(); if (!isAllowComment() && (isEOF() || !isSafeComment(stringVal))) { diff --git a/src/main/java/com/alibaba/druid/sql/parser/Lexer.java b/src/main/java/com/alibaba/druid/sql/parser/Lexer.java index a6ba9efb2c..9024b19208 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/Lexer.java +++ b/src/main/java/com/alibaba/druid/sql/parser/Lexer.java @@ -56,6 +56,8 @@ public class Lexer { protected Keywords keywods = Keywords.DEFAULT_KEYWORDS; protected String stringVal; + + protected String commentVal; protected boolean skipComment = true; @@ -73,9 +75,24 @@ public class Lexer { protected boolean hasComment = false; protected boolean endOfComment = false; + + protected boolean keepComments = false; public Lexer(String input){ + this(input, null); + } + + public Lexer(String input, CommentHandler commentHandler){ this(input, true); + this.commentHandler = commentHandler; + } + + public boolean isKeepComments() { + return keepComments; + } + + public void setKeepComments(boolean keepComments) { + this.keepComments = keepComments; } public CommentHandler getCommentHandler() { @@ -270,6 +287,7 @@ public class Lexer { public final void nextToken() { bufPos = 0; + hasComment = false; for (;;) { if (isWhitespace(ch)) { @@ -759,6 +777,8 @@ public class Lexer { } private void scanMultiLineComment() { + Token lastToken = this.token; + scanChar(); scanChar(); mark = pos; @@ -782,12 +802,25 @@ public class Lexer { stringVal = subString(mark, bufPos); token = Token.MULTI_LINE_COMMENT; hasComment = true; + if (keepComments) { + commentVal = stringVal; + } + + if (commentHandler != null && commentHandler.handle(lastToken, stringVal)) { + return; + } + + if (!isAllowComment() && !isSafeComment(stringVal)) { + throw new NotAllowCommentException(); + } } private void scanSingleLineComment() { + Token lastToken = this.token; + scanChar(); scanChar(); - mark = pos; + mark = pos - 1; bufPos = 0; for (;;) { @@ -817,6 +850,17 @@ public class Lexer { stringVal = subString(mark, bufPos); token = Token.LINE_COMMENT; hasComment = true; + if (keepComments) { + commentVal = stringVal; + } + + if (commentHandler != null && commentHandler.handle(lastToken, stringVal)) { + return; + } + + if (!isAllowComment() && !isSafeComment(stringVal)) { + throw new NotAllowCommentException(); + } } public void scanIdentifier() { @@ -972,6 +1016,10 @@ public class Lexer { public final String stringVal() { return stringVal; } + + public final String commentVal() { + return commentVal; + } private boolean isOperator(char ch) { switch (ch) { @@ -1080,11 +1128,10 @@ public class Lexer { } public static interface CommentHandler { - boolean handle(Token lastToken, String comment); } - public boolean isHasComment() { + public boolean hasComment() { return hasComment; } 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 7ae7d02a8f..d887fb950e 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java @@ -1179,6 +1179,10 @@ public class SQLExprParser extends SQLParser { public SQLExpr andRest(SQLExpr expr) { for (;;) { if (lexer.token() == Token.AND || lexer.token() == Token.AMPAMP) { + if (lexer.isKeepComments() && lexer.hasComment()) { + expr.addAfterComment(lexer.commentVal()); + } + lexer.nextToken(); SQLExpr rightExp = relational(); @@ -1682,7 +1686,12 @@ public class SQLExprParser extends SQLParser { item.setValue(new SQLIdentifierExpr(lexer.stringVal())); lexer.nextToken(); } else { - item.setValue(expr()); + if (lexer.token() == Token.ALL) { + item.setValue(new SQLIdentifierExpr(lexer.stringVal())); + lexer.nextToken(); + } else { + item.setValue(expr()); + } } return item; diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java index 898f54aa74..b552092298 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java @@ -158,6 +158,12 @@ public class SQLSelectParser extends SQLParser { return queryRest(select); } + + SQLSelectQueryBlock queryBlock = new SQLSelectQueryBlock(); + + if (lexer.hasComment() && lexer.isKeepComments()) { + queryBlock.addBeforeComment(lexer.commentVal()); + } accept(Token.SELECT); @@ -165,8 +171,6 @@ public class SQLSelectParser extends SQLParser { lexer.nextToken(); } - SQLSelectQueryBlock queryBlock = new SQLSelectQueryBlock(); - if (lexer.token() == Token.DISTINCT) { queryBlock.setDistionOption(SQLSetQuantifier.DISTINCT); lexer.nextToken(); @@ -234,7 +238,15 @@ public class SQLSelectParser extends SQLParser { if (lexer.token() == Token.WHERE) { lexer.nextToken(); - queryBlock.setWhere(expr()); + SQLExpr where = expr(); + + if (lexer.hasComment() && lexer.isKeepComments() // + && lexer.token() != Token.INSERT // odps multi-insert + ) { + where.addAfterComment(lexer.commentVal()); + } + + queryBlock.setWhere(where); } } @@ -326,7 +338,13 @@ public class SQLSelectParser extends SQLParser { parseTableSourceQueryTableExpr(tableReference); - return parseTableSourceRest(tableReference); + SQLTableSource tableSrc = parseTableSourceRest(tableReference); + + if (lexer.hasComment() && lexer.isKeepComments()) { + tableSrc.addAfterComment(lexer.commentVal()); + } + + return tableSrc; } private void parseTableSourceQueryTableExpr(SQLExprTableSource tableReference) { 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 831e722208..48924b9b9f 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java @@ -88,12 +88,16 @@ import com.alibaba.druid.sql.dialect.odps.parser.OdpsSelectParser; public class SQLStatementParser extends SQLParser { - protected SQLExprParser exprParser; + protected SQLExprParser exprParser; - protected boolean parseCompleteValues = true; - - protected int parseValuesSize = 3; + protected boolean parseCompleteValues = true; + protected int parseValuesSize = 3; + + protected List comments; + + protected CommentCallback commentCallBack = new CommentCallback(); + public SQLStatementParser(String sql){ this(sql, null); } @@ -101,11 +105,23 @@ public class SQLStatementParser extends SQLParser { public SQLStatementParser(String sql, String dbType){ this(new SQLExprParser(sql, dbType)); } - + public SQLStatementParser(SQLExprParser exprParser){ super(exprParser.getLexer(), exprParser.getDbType()); this.exprParser = exprParser; } + + protected SQLStatementParser(Lexer lexer, String dbType){ + super(lexer, dbType); + } + + public boolean isKeepComments() { + return lexer.isKeepComments(); + } + + public void setKeepComments(boolean keepComments) { + this.lexer.setKeepComments(keepComments); + } public SQLExprParser getExprParser() { return exprParser; @@ -122,13 +138,30 @@ public class SQLStatementParser extends SQLParser { } public void parseStatementList(List statementList, int max) { + List comments = null; + if (this.comments != null) { + comments = this.comments; + this.comments = null; + } + + int size_original = statementList.size(); + for (;;) { + boolean isFirstStmt = statementList.size() == size_original + 1; + if (isFirstStmt && comments != null && lexer.isKeepComments()) { + SQLStatement firstStmt = statementList.get(size_original); + for (String comment : comments) { + firstStmt.addBeforeComment(comment); + } + comments = null; + } + if (max != -1) { if (statementList.size() >= max) { return; } } - + if (lexer.token() == Token.EOF) { return; } @@ -136,8 +169,15 @@ public class SQLStatementParser extends SQLParser { return; } - if (lexer.token() == (Token.SEMI)) { + if (lexer.token() == Token.SEMI) { + size_original = statementList.size(); + this.comments = null; lexer.nextToken(); + comments = this.comments; + if (lexer.isKeepComments()) { + SQLStatement stmt = statementList.get(statementList.size() - 1); + stmt.getAttributes().put("format.semi", Boolean.TRUE); + } continue; } @@ -1781,4 +1821,22 @@ public class SQLStatementParser extends SQLParser { public void setParseValuesSize(int parseValuesSize) { this.parseValuesSize = parseValuesSize; } + + class CommentCallback implements Lexer.CommentHandler { + + @Override + public boolean handle(Token lastToken, String comment) { + addComment(comment); + + return true; + } + + } + + void addComment(String comment) { + if (comments == null) { + comments = new ArrayList(); + } + comments.add(comment); + } } diff --git a/src/main/java/com/alibaba/druid/sql/visitor/ParameterizedOutputVisitorUtils.java b/src/main/java/com/alibaba/druid/sql/visitor/ParameterizedOutputVisitorUtils.java index debb6b8311..3238d7a73f 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/ParameterizedOutputVisitorUtils.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/ParameterizedOutputVisitorUtils.java @@ -66,7 +66,7 @@ public class ParameterizedOutputVisitorUtils { stmt.accept(visitor); } - if (visitor.getReplaceCount() == 0 && !parser.getLexer().isHasComment()) { + if (visitor.getReplaceCount() == 0 && !parser.getLexer().hasComment()) { return sql; } diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java index 94b4121534..e8666f2a83 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -350,6 +350,10 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Printab visitBinaryLeft(item, x.getOperator()); if (relational) { + if (isPrettyFormat() && item.hasAfterComment()) { + print(' '); + printComment(item.getAfterCommentsDirect(), "\n"); + } println(); } else { print(" "); @@ -684,6 +688,10 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Printab } public boolean visit(SQLSelectQueryBlock x) { + if (isPrettyFormat() && x.hasBeforeComment()) { + printComment(x.getBeforeCommentsDirect(), "\n"); + } + print("SELECT "); if (SQLSetQuantifier.ALL == x.getDistionOption()) { @@ -763,11 +771,16 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Printab public boolean visit(SQLExprTableSource x) { x.getExpr().accept(this); - + if (x.getAlias() != null) { print(' '); print(x.getAlias()); } + + if (isPrettyFormat() && x.hasAfterComment()) { + print(' '); + printComment(x.getAfterCommentsDirect(), "\n"); + } return false; } @@ -2182,4 +2195,16 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Printab } return false; } + + protected void printComment(List comments, String seperator) { + if (comments != null) { + for (int i = 0; i < comments.size(); ++i) { + if (i != 0) { + print(seperator); + } + String comment = comments.get(i); + print(comment); + } + } + } } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlFormatTest.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlFormatTest.java index 2c71a5771a..03988e9d29 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlFormatTest.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlFormatTest.java @@ -29,6 +29,7 @@ public class MySqlFormatTest extends TestCase { "\ta INT, \n" + // "\tb CHAR(20), \n" + // "\tINDEX(a)\n" + // - ")", SQLUtils.format(text, JdbcUtils.MYSQL)); + ")" // + + "\n;", SQLUtils.format(text, JdbcUtils.MYSQL)); } } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsFormatCommentTest.java b/src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsFormatCommentTest.java new file mode 100644 index 0000000000..1b9389c4e9 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsFormatCommentTest.java @@ -0,0 +1,34 @@ +package com.alibaba.druid.bvt.sql.odps; + +import org.junit.Assert; + +import com.alibaba.druid.sql.SQLUtils; + +import junit.framework.TestCase; + +public class OdpsFormatCommentTest extends TestCase { + public void test_column_comment() throws Exception { + String sql = "select f1 -- aaa" + + "\n from t1"; + Assert.assertEquals("SELECT f1 -- aaa" // + + "\nFROM t1", SQLUtils.formatOdps(sql)); + } + + public void test_column_2_comment() throws Exception { + String sql = "select f1 -- aaa" + + "\n, f2 -- bbb" + + "\n from t1"; + Assert.assertEquals("SELECT f1, -- aaa" // + + "\n\tf2 -- bbb" // + + "\nFROM t1", SQLUtils.formatOdps(sql)); + } + + public void test_column_2_multi_comment() throws Exception { + String sql = "select f1 /*aa*/" + + "\n, f2 -- bbb" + + "\n from t1"; + Assert.assertEquals("SELECT f1, /*aa*/" // + + "\n\tf2 -- bbb" // + + "\nFROM t1", SQLUtils.formatOdps(sql)); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsFormatCommentTest2.java b/src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsFormatCommentTest2.java new file mode 100644 index 0000000000..13a7cc370c --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsFormatCommentTest2.java @@ -0,0 +1,27 @@ +package com.alibaba.druid.bvt.sql.odps; + +import org.junit.Assert; + +import com.alibaba.druid.sql.SQLUtils; + +import junit.framework.TestCase; + +public class OdpsFormatCommentTest2 extends TestCase { + public void test_column_comment() throws Exception { + String sql = "--[Subject -]" // + + "\n--[Author -高铁/035139]"// + + "\n--[Created -2015-06-10 13:19:18]"// + + "\n--[Update ]"// + + "\nset odps.sql.mapper.split.size=2048;"// + + "\nselect * from dual;"; + Assert.assertEquals("--[Subject -]" + + "\n--[Author -高铁/035139]" + + "\n--[Created -2015-06-10 13:19:18]" + + "\n--[Update ]" + + "\nSET odps.sql.mapper.split.size = 2048;" + + "\nSELECT *" + + "\nFROM dual" + + "\n;", SQLUtils.formatOdps(sql)); + } + +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsFormatCommentTest3.java b/src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsFormatCommentTest3.java new file mode 100644 index 0000000000..6a6043d29b --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsFormatCommentTest3.java @@ -0,0 +1,30 @@ +package com.alibaba.druid.bvt.sql.odps; + +import org.junit.Assert; + +import com.alibaba.druid.sql.SQLUtils; + +import junit.framework.TestCase; + +public class OdpsFormatCommentTest3 extends TestCase { + public void test_column_comment() throws Exception { + String sql = "-- 使用服务模式" // + + "\nset odps.service.mode=all;" // + + "\n-- 使用新引擎"// + + "\nset odps.nvm.enabled=true;"// + + "\nselect f1 -- aa"// + + "\nfrom t0;"// + + "\nselect f2 -- aa"// + + "\nfrom t1;";// + Assert.assertEquals("-- 使用服务模式"// + + "\nSET odps.service.mode = all;"// + + "\n-- 使用新引擎"// + + "\nSET odps.nvm.enabled = true;"// + + "\nSELECT f1 -- aa"// + + "\nFROM t0;"// + + "\nSELECT f2 -- aa"// + + "\nFROM t1" + + "\n;", SQLUtils.formatOdps(sql)); + } + +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsFormatCommentTest4.java b/src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsFormatCommentTest4.java new file mode 100644 index 0000000000..b9dde8421a --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsFormatCommentTest4.java @@ -0,0 +1,40 @@ +package com.alibaba.druid.bvt.sql.odps; + +import org.junit.Assert; + +import com.alibaba.druid.sql.SQLUtils; + +import junit.framework.TestCase; + +public class OdpsFormatCommentTest4 extends TestCase { + public void test_column_comment() throws Exception { + String sql = "from (select * from xxx) a" + + "\n -- comment_0" // + + "\ninsert overwrite table b partition(ds='20150711')" // + + "\nselect f0, f1, f2" // + + "\nwhere name rlike 'xxxx'" + + "\n -- comment_1" // + + "\ninsert overwrite table c partition(ds='20150711')" // + + "\nselect f0, f1, f2" // + + "\nwhere name rlike 'kk';" + ;// + Assert.assertEquals("FROM (" // + + "\n\tSELECT *"// + + "\n\tFROM xxx"// + + "\n) a" // + + "\n-- comment_0"// + + "\nINSERT OVERWRITE TABLE b PARTITION (ds='20150711')"// + + "\nSELECT f0, "// + + "\n\tf1, "// + + "\n\tf2"// + + "\nWHERE name RLIKE 'xxxx'" // + + "\n-- comment_1"// + + "\nINSERT OVERWRITE TABLE c PARTITION (ds='20150711')"// + + "\nSELECT f0, "// + + "\n\tf1, "// + + "\n\tf2"// + + "\nWHERE name RLIKE 'kk'" + + "\n;", SQLUtils.formatOdps(sql)); + } + +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsFormatCommentTest5.java b/src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsFormatCommentTest5.java new file mode 100644 index 0000000000..a7086e7bb2 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsFormatCommentTest5.java @@ -0,0 +1,48 @@ +package com.alibaba.druid.bvt.sql.odps; + +import org.junit.Assert; + +import com.alibaba.druid.sql.SQLUtils; + +import junit.framework.TestCase; + +public class OdpsFormatCommentTest5 extends TestCase { + public void test_column_comment() throws Exception { + String sql = "select *" // + + "\nfrom t -- xxxx"// + + "\nwhere id > 0;" + ;// + Assert.assertEquals("SELECT *" // + + "\nFROM t -- xxxx" // + + "\nWHERE id > 0" + + "\n;", SQLUtils.formatOdps(sql)); + } + + public void test_column_comment_as() throws Exception { + String sql = "select *" // + + "\nfrom xxxx a-- xxxx"// + + "\nwhere id > 0;" + ;// + Assert.assertEquals("SELECT *" // + + "\nFROM xxxx a -- xxxx" // + + "\nWHERE id > 0" + + "\n;", SQLUtils.formatOdps(sql)); + } + + + public void test_column_comment_subquery() throws Exception { + String sql = "select *" // + + "\nfrom (" // + + "\n-- comment_xxx" // + + "\nselect * from t" // + + "\n) a;" + ;// + Assert.assertEquals("SELECT *" // + + "\nFROM (" // + + "\n\t-- comment_xxx" // + + "\n\tSELECT *" // + + "\n\tFROM t" // + + "\n) a" + + "\n;", SQLUtils.formatOdps(sql)); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsFormatCommentTest6.java b/src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsFormatCommentTest6.java new file mode 100644 index 0000000000..4422238c98 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsFormatCommentTest6.java @@ -0,0 +1,25 @@ +package com.alibaba.druid.bvt.sql.odps; + +import org.junit.Assert; + +import com.alibaba.druid.sql.SQLUtils; + +import junit.framework.TestCase; + +public class OdpsFormatCommentTest6 extends TestCase { + public void test_column_comment() throws Exception { + String sql = "select *" // + + "\nfrom t "// + + "\nwhere status = '20' -- comment xxx" + + "\nand flag & 127 > 0 -- comment kkkkk" + + "\n;" + ;// + Assert.assertEquals("SELECT *" + + "\nFROM t" + + "\nWHERE status = '20' -- comment xxx" + + "\n\tAND flag & 127 > 0 -- comment kkkkk" + + "\n;", SQLUtils.formatOdps(sql)); + } + + +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsFormatTest.java b/src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsFormatTest.java new file mode 100644 index 0000000000..f83c584fd9 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsFormatTest.java @@ -0,0 +1,26 @@ +package com.alibaba.druid.bvt.sql.odps; + +import org.junit.Assert; + +import com.alibaba.druid.sql.SQLUtils; + +import junit.framework.TestCase; + +public class OdpsFormatTest extends TestCase { + public void test_format() throws Exception { + String sql = "select * from t1; ;select * from t2;"; + Assert.assertEquals("SELECT *" // + + "\nFROM t1;" // + + "\nSELECT *" // + + "\nFROM t2"// + + "\n;", SQLUtils.formatOdps(sql)); + } + + public void test_no_semi() throws Exception { + String sql = "select * from t1; ;select * from t2"; + Assert.assertEquals("SELECT *" // + + "\nFROM t1;" // + + "\nSELECT *" // + + "\nFROM t2", SQLUtils.formatOdps(sql)); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGFormatTest.java b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGFormatTest.java index 3119c464fd..3958c882bd 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGFormatTest.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/PGFormatTest.java @@ -30,6 +30,7 @@ public class PGFormatTest extends TestCase { "\n\tfooid int," + // "\n\tfoosubid int," + // "\n\tfooname text" + // - "\n)", formatedSql); + "\n)" + + "\n;", formatedSql); } }