From 3c98a1eee5effb6b368f533f11b507e09ab7eb64 Mon Sep 17 00:00:00 2001 From: wenshao Date: Sun, 17 Sep 2017 17:11:26 +0800 Subject: [PATCH] improved sql parser. --- .../alibaba/druid/sql/SQLTransformUtils.java | 13 +- .../alibaba/druid/sql/ast/SQLDataType.java | 1 + .../sql/ast/expr/SQLMethodInvokeExpr.java | 47 ++- .../druid/sql/ast/expr/SQLNumberExpr.java | 2 +- .../ast/statement/SQLColumnDefinition.java | 17 +- .../dialect/mysql/parser/MySqlExprParser.java | 6 + .../sql/dialect/mysql/parser/MySqlLexer.java | 83 +++++ .../com/alibaba/druid/sql/parser/Lexer.java | 2 +- .../druid/sql/parser/SQLExprParser.java | 4 +- .../druid/sql/parser/SQLSelectParser.java | 14 +- .../alibaba/druid/sql/parser/SymbolTable.java | 61 ++- .../ParameterizedOutputVisitorUtils.java | 2 +- .../java/com/alibaba/druid/util/FnvHash.java | 27 ++ .../druid/bvt/sql/SymbolTableTest.java | 50 +++ .../alibaba/druid/bvt/sql/TestNewSpout.java | 346 ++++++++++++++++++ .../MySqlSelectTest_60_firstComment.java | 67 ++++ .../MySqlSelectTest_61_firstComment_2.java | 67 ++++ .../select/MySqlSelectTest_62_optimized.java | 67 ++++ .../sql/postgresql/select/PGSelectTest57.java | 74 ++++ .../Oracle2MySql_method_sys_guid.java | 18 + .../Oracle2PG_DataTypeTest_chars.java | 8 + .../Oracle2PG_DataTypeTest_double.java | 8 + .../Oracle2PG_DataTypeTest_number_int.java | 2 +- 23 files changed, 955 insertions(+), 31 deletions(-) create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/SymbolTableTest.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/TestNewSpout.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/mysql/select/MySqlSelectTest_60_firstComment.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/mysql/select/MySqlSelectTest_61_firstComment_2.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/mysql/select/MySqlSelectTest_62_optimized.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest57.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/transform/datatype/oracle2pg/Oracle2MySql_method_sys_guid.java diff --git a/src/main/java/com/alibaba/druid/sql/SQLTransformUtils.java b/src/main/java/com/alibaba/druid/sql/SQLTransformUtils.java index 6cf05df59f..1fdaa88327 100644 --- a/src/main/java/com/alibaba/druid/sql/SQLTransformUtils.java +++ b/src/main/java/com/alibaba/druid/sql/SQLTransformUtils.java @@ -446,7 +446,7 @@ public class SQLTransformUtils { int precision, scale = 0; if (arg0 instanceof SQLAllColumnExpr) { precision = 19; - scale = 0; + scale = -1; } else { precision = ((SQLIntegerExpr) arg0).getNumber().intValue(); } @@ -476,6 +476,8 @@ public class SQLTransformUtils { } else { dataType = new SQLDataTypeImpl(SQLDataType.Constants.DECIMAL, precision); } + } else if (scale == -1) { + dataType = new SQLDataTypeImpl(SQLDataType.Constants.DOUBLE_PRECISION); } else { dataType = new SQLDataTypeImpl(SQLDataType.Constants.DECIMAL, precision, scale); } @@ -622,4 +624,13 @@ public class SQLTransformUtils { return dataType; } + + public static SQLExpr transformOracleToPostgresql(SQLMethodInvokeExpr x) { + long nameHashCode64 = x.methodNameHashCode64(); + if (nameHashCode64 == FnvHash.Constants.SYS_GUID) { + SQLMethodInvokeExpr uuid_generate_v4 = new SQLMethodInvokeExpr("uuid_generate_v4"); + return uuid_generate_v4; + } + return x; + } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/SQLDataType.java b/src/main/java/com/alibaba/druid/sql/ast/SQLDataType.java index a1ab24ef73..c71688b4ef 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/SQLDataType.java +++ b/src/main/java/com/alibaba/druid/sql/ast/SQLDataType.java @@ -41,6 +41,7 @@ public interface SQLDataType extends SQLObject { String CHAR = "CHAR"; String NCHAR = "NCHAR"; String VARCHAR = "VARCHAR"; + String DATE = "DATE"; String TIMESTAMP = "TIMESTAMP"; String XML = "XML"; diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLMethodInvokeExpr.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLMethodInvokeExpr.java index 323aa22345..686bda1e45 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLMethodInvokeExpr.java +++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLMethodInvokeExpr.java @@ -26,11 +26,12 @@ import com.alibaba.druid.sql.ast.SQLExprImpl; import com.alibaba.druid.sql.ast.SQLReplaceable; import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor; import com.alibaba.druid.sql.visitor.SQLASTVisitor; +import com.alibaba.druid.util.FnvHash; public class SQLMethodInvokeExpr extends SQLExprImpl implements SQLReplaceable, Serializable { private static final long serialVersionUID = 1L; - private String methodName; + private String name; private SQLExpr owner; private final List parameters = new ArrayList(); @@ -40,34 +41,50 @@ public class SQLMethodInvokeExpr extends SQLExprImpl implements SQLReplaceable, private String trimOption; + private long nameHashCode64; + public SQLMethodInvokeExpr(){ } public SQLMethodInvokeExpr(String methodName){ - this.methodName = methodName; + this.name = methodName; + } + + public SQLMethodInvokeExpr(String methodName, long nameHashCode64){ + this.name = methodName; + this.nameHashCode64 = nameHashCode64; } public SQLMethodInvokeExpr(String methodName, SQLExpr owner){ - this.methodName = methodName; + this.name = methodName; setOwner(owner); } public SQLMethodInvokeExpr(String methodName, SQLExpr owner, SQLExpr... params){ - this.methodName = methodName; + this.name = methodName; setOwner(owner); for (SQLExpr param : params) { this.addParameter(param); } } + public long methodNameHashCode64() { + if (nameHashCode64 == 0 + && name != null) { + nameHashCode64 = FnvHash.hashCode64(name); + } + return nameHashCode64; + } + public String getMethodName() { - return this.methodName; + return this.name; } public void setMethodName(String methodName) { - this.methodName = methodName; + this.name = methodName; + this.nameHashCode64 = 0L; } public SQLExpr getOwner() { @@ -106,7 +123,7 @@ public class SQLMethodInvokeExpr extends SQLExprImpl implements SQLReplaceable, buf.append("."); } - buf.append(this.methodName); + buf.append(this.name); buf.append("("); for (int i = 0, size = this.parameters.size(); i < size; ++i) { if (i != 0) { @@ -144,7 +161,7 @@ public class SQLMethodInvokeExpr extends SQLExprImpl implements SQLReplaceable, SQLMethodInvokeExpr that = (SQLMethodInvokeExpr) o; - if (methodName != null ? !methodName.equals(that.methodName) : that.methodName != null) return false; + if (name != null ? !name.equals(that.name) : that.name != null) return false; if (owner != null ? !owner.equals(that.owner) : that.owner != null) return false; if (parameters != null ? !parameters.equals(that.parameters) : that.parameters != null) return false; return from != null ? from.equals(that.from) : that.from == null; @@ -153,7 +170,7 @@ public class SQLMethodInvokeExpr extends SQLExprImpl implements SQLReplaceable, @Override public int hashCode() { - int result = methodName != null ? methodName.hashCode() : 0; + int result = name != null ? name.hashCode() : 0; result = 31 * result + (owner != null ? owner.hashCode() : 0); result = 31 * result + (parameters != null ? parameters.hashCode() : 0); result = 31 * result + (from != null ? from.hashCode() : 0); @@ -163,7 +180,7 @@ public class SQLMethodInvokeExpr extends SQLExprImpl implements SQLReplaceable, public SQLMethodInvokeExpr clone() { SQLMethodInvokeExpr x = new SQLMethodInvokeExpr(); - x.methodName = methodName; + x.name = name; if (owner != null) { x.setOwner(owner.clone()); @@ -204,7 +221,7 @@ public class SQLMethodInvokeExpr extends SQLExprImpl implements SQLReplaceable, return false; } - if (!SQLUtils.nameEquals(function, methodName)) { + if (!SQLUtils.nameEquals(function, name)) { return false; } @@ -224,19 +241,19 @@ public class SQLMethodInvokeExpr extends SQLExprImpl implements SQLReplaceable, } public SQLDataType computeDataType() { - if (SQLUtils.nameEquals("to_date", methodName) - || SQLUtils.nameEquals("add_months", methodName)) { + if (SQLUtils.nameEquals("to_date", name) + || SQLUtils.nameEquals("add_months", name)) { return SQLDateExpr.DEFAULT_DATA_TYPE; } if (parameters.size() == 1) { - if (SQLUtils.nameEquals("trunc", methodName)) { + if (SQLUtils.nameEquals("trunc", name)) { return parameters.get(0).computeDataType(); } } else if (parameters.size() == 2) { SQLExpr param0 = parameters.get(0); SQLExpr param1 = parameters.get(1); - if (SQLUtils.nameEquals("nvl", methodName) || SQLUtils.nameEquals("ifnull", methodName)) { + if (SQLUtils.nameEquals("nvl", name) || SQLUtils.nameEquals("ifnull", name)) { SQLDataType dataType = param0.computeDataType(); if (dataType != null) { return dataType; diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLNumberExpr.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLNumberExpr.java index b34974a2e1..b1b2643a61 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLNumberExpr.java +++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLNumberExpr.java @@ -24,7 +24,7 @@ import java.io.IOException; import java.math.BigDecimal; public class SQLNumberExpr extends SQLNumericLiteralExpr implements SQLValuableExpr { - private static SQLDataType defaultDataType = new SQLDataTypeImpl("number"); + public final static SQLDataType defaultDataType = new SQLDataTypeImpl("number"); private Number number; diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLColumnDefinition.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLColumnDefinition.java index 09c26eb759..a1f55c597e 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLColumnDefinition.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLColumnDefinition.java @@ -26,7 +26,7 @@ import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; import com.alibaba.druid.sql.visitor.SQLASTVisitor; import com.alibaba.druid.util.JdbcConstants; -public class SQLColumnDefinition extends SQLObjectImpl implements SQLTableElement, SQLObjectWithDataType { +public class SQLColumnDefinition extends SQLObjectImpl implements SQLTableElement, SQLObjectWithDataType, SQLReplaceable { protected String dbType; protected SQLName name; @@ -250,6 +250,21 @@ public class SQLColumnDefinition extends SQLObjectImpl implements SQLTableElemen this.storage = storage; } + @Override + public boolean replace(SQLExpr expr, SQLExpr target) { + if (defaultExpr == expr) { + setDefaultExpr(target); + return true; + } + + if (name == expr) { + setName((SQLName) target); + return true; + } + + return false; + } + public static class Identity extends SQLObjectImpl { private Integer seed; 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 c10aab4f91..ecc4eaa86d 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 @@ -124,6 +124,12 @@ public class MySqlExprParser extends SQLExprParser { lexer.reset(6, ' ', Token.UPDATE); return; } + + if (c0 == '/' && c1 == '*' && isEnabled(SQLParserFeature.OptimizedForParameterized)) { + MySqlLexer mySqlLexer = (MySqlLexer) lexer; + mySqlLexer.skipFirstHintsOrMultiCommentAndNextToken(); + return; + } } this.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 c64a82eced..834b83cc2f 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 @@ -401,6 +401,89 @@ public class MySqlLexer extends Lexer { scanString2(); } + public void skipFirstHintsOrMultiCommentAndNextToken() { + int starIndex = pos + 2; + + for (;;) { + starIndex = text.indexOf('*', starIndex); + if (starIndex == -1 || starIndex == text.length() - 1) { + this.token = Token.ERROR; + return; + } + + int slashIndex = starIndex + 1; + if (charAt(slashIndex) == '/') { + pos = slashIndex + 1; + ch = text.charAt(pos); + if (pos < text.length() - 6) { + int pos_6 = pos + 6; + char c0 = ch; + char c1 = text.charAt(pos + 1); + char c2 = text.charAt(pos + 2); + char c3 = text.charAt(pos + 3); + char c4 = text.charAt(pos + 4); + char c5 = text.charAt(pos + 5); + char c6 = text.charAt(pos_6); + if (c0 == 's' && c1 == 'e' && c2 == 'l' && c3 == 'e' && c4 == 'c' && c5 == 't' && c6 == ' ') { + this.comments = null; + reset(pos_6, ' ', Token.SELECT); + return; + } + + if (c0 == 'i' && c1 == 'n' && c2 == 's' && c3 == 'e' && c4 == 'r' && c5 == 't' && c6 == ' ') { + this.comments = null; + reset(pos_6, ' ', Token.INSERT); + return; + } + + if (c0 == 'u' && c1 == 'p' && c2 == 'd' && c3 == 'a' && c4 == 't' && c5 == 'e' && c6 == ' ') { + this.comments = null; + reset(pos_6, ' ', Token.UPDATE); + return; + } + + + if (c0 == 'd' && c1 == 'e' && c2 == 'l' && c3 == 'e' && c4 == 't' && c5 == 'e' && c6 == ' ') { + this.comments = null; + reset(pos_6, ' ', Token.DELETE); + return; + } + + if (c0 == 'S' && c1 == 'E' && c2 == 'L' && c3 == 'E' && c4 == 'C' && c5 == 'T' && c6 == ' ') { + this.comments = null; + reset(pos_6, ' ', Token.SELECT); + return; + } + + if (c0 == 'I' && c1 == 'N' && c2 == 'S' && c3 == 'E' && c4 == 'R' && c5 == 'T' && c6 == ' ') { + this.comments = null; + reset(pos_6, ' ', Token.INSERT); + return; + } + + if (c0 == 'U' && c1 == 'P' && c2 == 'D' && c3 == 'A' && c4 == 'T' && c5 == 'E' && c6 == ' ') { + this.comments = null; + reset(pos_6, ' ', Token.UPDATE); + return; + } + + if (c0 == 'D' && c1 == 'E' && c2 == 'L' && c3 == 'E' && c4 == 'T' && c5 == 'E' && c6 == ' ') { + this.comments = null; + reset(pos_6, ' ', Token.DELETE); + return; + } + + nextToken(); + return; + } else { + nextToken(); + return; + } + } + starIndex++; + } + } + public void scanComment() { Token lastToken = this.token; 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 461028d28c..0931d1b872 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/Lexer.java +++ b/src/main/java/com/alibaba/druid/sql/parser/Lexer.java @@ -60,7 +60,7 @@ public class Lexer { protected long hash; protected int commentCount = 0; - protected List comments = new ArrayList(2); + protected List comments = null; protected boolean skipComment = true; private SavePoint savePoint = null; 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 44f86acc53..dbb77e8c81 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java @@ -913,7 +913,7 @@ public class SQLExprParser extends SQLParser { SQLExpr owner = null; String trimOption = null; - long hash_lower; + long hash_lower = 0L; if (expr instanceof SQLIdentifierExpr) { SQLIdentifierExpr identifierExpr = (SQLIdentifierExpr) expr; methodName = identifierExpr.getName(); @@ -964,7 +964,7 @@ public class SQLExprParser extends SQLParser { return aggregateExpr; } - methodInvokeExpr = new SQLMethodInvokeExpr(methodName); + methodInvokeExpr = new SQLMethodInvokeExpr(methodName, hash_lower); if (owner != null) { methodInvokeExpr.setOwner(owner); } 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 54dc202a1a..44697d92f3 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java @@ -565,10 +565,16 @@ public class SQLSelectParser extends SQLParser { protected SQLTableSource parseTableSourceRest(SQLTableSource tableSource) { if ((tableSource.getAlias() == null) || (tableSource.getAlias().length() == 0)) { - if (lexer.token != Token.LEFT && lexer.token != Token.RIGHT && lexer.token != Token.FULL - && (!lexer.identifierEquals(FnvHash.Constants.STRAIGHT_JOIN)) - && (!lexer.identifierEquals(FnvHash.Constants.CROSS)) - && lexer.token != Token.OUTER) { + Token token = lexer.token; + long hash; + if (token != Token.LEFT + && token != Token.RIGHT + && token != Token.FULL + && token != Token.OUTER + && !(token == Token.IDENTIFIER + && ((hash = lexer.hash_lower()) == FnvHash.Constants.STRAIGHT_JOIN + || hash == FnvHash.Constants.CROSS))) + { String alias = tableAlias(); if (alias != null) { tableSource.setAlias(alias); diff --git a/src/main/java/com/alibaba/druid/sql/parser/SymbolTable.java b/src/main/java/com/alibaba/druid/sql/parser/SymbolTable.java index f8abd64f63..e36d83ae8f 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SymbolTable.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SymbolTable.java @@ -15,10 +15,14 @@ */ package com.alibaba.druid.sql.parser; +import java.nio.charset.Charset; + /** * @author wenshao[szujobs@hotmail.com] */ public class SymbolTable { + private static final Charset UTF8 = Charset.forName("UTF-8"); + public static SymbolTable global = new SymbolTable(8192); private final Entry[] entries; @@ -29,15 +33,12 @@ public class SymbolTable { this.entries = new Entry[tableSize]; } - - public String addSymbol(String buffer, int offset, int len, long hash) { final int bucket = ((int) hash) & indexMask; Entry entry = entries[bucket]; if (entry != null) { - if (hash == entry.hash // - && len == entry.len) { + if (hash == entry.hash) { return entry.value; } @@ -52,12 +53,64 @@ public class SymbolTable { return str; } + public String addSymbol(byte[] buffer, int offset, int len, long hash) { + final int bucket = ((int) hash) & indexMask; + + Entry entry = entries[bucket]; + if (entry != null) { + if (hash == entry.hash) { + return entry.value; + } + + String str = subString(buffer, offset, len); + + return str; + } + + String str = subString(buffer, offset, len); + entry = new Entry(hash, len, str); + entries[bucket] = entry; + return str; + } + + public String addSymbol(String symbol, long hash) { + final int bucket = ((int) hash) & indexMask; + + Entry entry = entries[bucket]; + if (entry != null) { + if (hash == entry.hash) { + return entry.value; + } + + return symbol; + } + + entry = new Entry(hash, symbol.length(), symbol); + entries[bucket] = entry; + return symbol; + } + + public String findSymbol(long hash) { + final int bucket = ((int) hash) & indexMask; + Entry entry = entries[bucket]; + if (entry != null && entry.hash == hash) { + return entry.value; + } + return null; + } + private static String subString(String src, int offset, int len) { char[] chars = new char[len]; src.getChars(offset, offset + len, chars, 0); return new String(chars); } + private static String subString(byte[] bytes, int from, int len) { + byte[] strBytes = new byte[len]; + System.arraycopy(bytes, from, strBytes, 0, len); + return new String(strBytes, UTF8); + } + private static class Entry { public final long hash; public final int len; 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 8b6c78e1b4..ef75ef5a0e 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/ParameterizedOutputVisitorUtils.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/ParameterizedOutputVisitorUtils.java @@ -65,7 +65,7 @@ public class ParameterizedOutputVisitorUtils { } if (visitor.getReplaceCount() == 0 - && parser.getLexer().getCommentCount() == 0) { + && parser.getLexer().getCommentCount() == 0 && sql.charAt(0) != '/') { return sql; } diff --git a/src/main/java/com/alibaba/druid/util/FnvHash.java b/src/main/java/com/alibaba/druid/util/FnvHash.java index a180c9ae1d..6cd313e2d5 100644 --- a/src/main/java/com/alibaba/druid/util/FnvHash.java +++ b/src/main/java/com/alibaba/druid/util/FnvHash.java @@ -55,6 +55,25 @@ public final class FnvHash { return hash; } + public static long fnv1a_64(byte[] input, int offset, int end) { + if (input == null) { + return 0; + } + + if (input.length < end) { + end = input.length; + } + + long hash = BASIC; + for (int i = offset; i < end; ++i) { + byte c = input[i]; + hash ^= c; + hash *= PRIME; + } + + return hash; + } + public static long fnv1a_64(char[] chars) { if (chars == null) { return 0; @@ -468,5 +487,13 @@ public final class FnvHash { long SOURCE = fnv1a_64_lower("SOURCE"); long STAR = fnv1a_64_lower("*"); + + long TO_CHAR = fnv1a_64_lower("TO_CHAR"); + long SYS_GUID = fnv1a_64_lower("SYS_GUID"); + + long STATISTICS = fnv1a_64_lower("STATISTICS"); + long TRANSACTION = fnv1a_64_lower("TRANSACTION"); + long OFF = fnv1a_64_lower("OFF"); + long IDENTITY_INSERT = fnv1a_64_lower("IDENTITY_INSERT"); } } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/SymbolTableTest.java b/src/test/java/com/alibaba/druid/bvt/sql/SymbolTableTest.java new file mode 100644 index 0000000000..0982a73aab --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/SymbolTableTest.java @@ -0,0 +1,50 @@ +package com.alibaba.druid.bvt.sql; + +import com.alibaba.druid.sql.parser.SymbolTable; +import com.alibaba.druid.util.FnvHash; +import junit.framework.TestCase; + +public class SymbolTableTest extends TestCase { + public void test_symbols() throws Exception { + SymbolTable symbols = new SymbolTable(65535); + + String[] strings = new String[10]; + for (int i = 0; i < strings.length; ++i) { + String str = "abc" + i; + strings[i] = str; + symbols.addSymbol(str, FnvHash.fnv1a_64(str)); + } + + for (int i = 0; i < strings.length; ++i) { + String str = strings[i]; + long hash = FnvHash.fnv1a_64(str); + String symbol = symbols.findSymbol(hash); + assertSame(str, symbol); + } + { + byte[] bytes = "kkk#abc0#aa".getBytes(); + long hash = FnvHash.fnv1a_64(bytes, 4, 8); + String symbol = symbols.addSymbol(bytes, 4, 8, hash); + assertSame(strings[0], symbol); + } + + byte[] bytes = "xab#time:3333".getBytes(); + System.out.println(indexOfTime(bytes, 1)); + System.out.println("xab#time:3333".indexOf("#time")); + } + + public static int indexOfTime(byte[] bytes, int fromIndex) { + int end = bytes.length - 5; + for (int i = fromIndex; i < end; ++i) { + if (bytes[i] == '#' + && bytes[i + 1] == 't' + && bytes[i + 2] == 'i' + && bytes[i + 3] == 'm' + && bytes[i + 4] == 'e') { + return i; + } + } + + return -1; + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/TestNewSpout.java b/src/test/java/com/alibaba/druid/bvt/sql/TestNewSpout.java new file mode 100644 index 0000000000..2499df21eb --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/TestNewSpout.java @@ -0,0 +1,346 @@ +package com.alibaba.druid.bvt.sql; + +import com.alibaba.druid.sql.parser.SymbolTable; +import com.alibaba.druid.util.FnvHash; + +import java.nio.charset.Charset; +import java.util.HashSet; +import java.util.Set; + +/** + * Created by yunning on 16/7/10. + */ +public class TestNewSpout { + + + public static int indexOf_nsharp(byte[] bytes, int fromIndex) { + int end = bytes.length - 2; + for (int i = fromIndex; i < end; ++i) { + if (bytes[i] == '\n' + && bytes[i + 1] == '#') { + return i; + } + } + + return -1; + } + + public static int indexOf_nReturn(byte[] bytes, int fromIndex) { + for (int i = fromIndex; i < bytes.length; ++i) { + if (bytes[i] == '\n') { + return i; + } + } + + return -1; + } + + public static int indexOfTime(byte[] bytes, int fromIndex) { + int end = bytes.length - 5; + for (int i = fromIndex; i < end; ++i) { + if (bytes[i] == '#' + && bytes[i + 1] == 't' + && bytes[i + 2] == 'i' + && bytes[i + 3] == 'm' + && bytes[i + 4] == 'e') { + return i; + } + } + + return -1; + } + + public static final SymbolTable dbSymbols = new SymbolTable(1024 * 256); + + public static String substring(byte[] bytes, int from, int to) { + int newLength = to - from; + byte[] copy = new byte[newLength]; + System.arraycopy(bytes, from, copy, 0, newLength); + return new String(copy, Charset.forName("UTF-8")); + } + + public static void main(String[] args) throws Exception { + final String datass = "#time:1470191976686205\n" + + "#user@host:monitor[monitor] @ [127.0.0.1]\n" + + "#db:test\n" + + "#table_name:aa\n" + + "set session time_zone='+08:00';\n" + + "#query_time:0.000028123456789987654321\n" + + "#lock_time:0.000000\n" + + "#rows_sent:0\n" + + "#rows_examined:0\n" + + "#rows_affected:0\n" + + "#innodb_pages_read:1\n" + + "#innodb_pages_io_read:2\n" + + "#id:55438\n" + + "#time:1470191976686207\n" + + "#user@host:monitor[monitor] @ [127.0.0.1]\n" + + "#db:test\n" + + "#table_name:aa\n" + + "#time:1470191976686206\n" + + "#user@host:monitor[monitor] @ [127.0.0.1]\n" + + "#db:test\n" + + "#table_name:aa\n" + + "set session time_zone='+0800';\n" + + "#query_time:0.000028123456789987654322\n" + + "#lock_time:0.000000\n" + + "#rows_sent:0\n" + + "#rows_examined:0\n" + + "#rows_affected:0\n" + + "#innodb_pages_read:0\n" + + "#innodb_pages_io_read:0\n" + + "#id:123"; + + byte[] datas = datass.getBytes(); + long start = System.currentTimeMillis(); + for (int i = 0; i < 1; i++) { + final int len = datas.length; + int offset = indexOfTime(datas, 0); + long now = System.nanoTime(); + while (offset != -1) { + int rowOffset = offset; + int k = 0; + final int[] offsets = new int[12]; + boolean isNoFirst = false; + while (rowOffset != -1 && k < 12) { + if (isNoFirst && rowOffset + 5 <= len - 1) { + if (datas[rowOffset + 2] == 't' && + datas[rowOffset + 3] == 'i' && + datas[rowOffset + 4] == 'm' && + datas[rowOffset + 5] == 'e') { + break; + } + } + offsets[k] = rowOffset; + rowOffset = indexOf_nsharp(datas, rowOffset + 1); + k = k + 1; + isNoFirst = true; + } + offset = rowOffset == -1 ? -1 : indexOfTime(datas, rowOffset + 1); + if (k < 12) { + continue; + } + SqlInfo sqlInfo = new SqlInfo(); + // sqlInfo.setHostName(hostName); + + boolean isError = false; + String sql = null; + + //time + int currItemOffset = offsets[0]; + int nextItemOffset = offsets[1]; + /* String item = datas.substring(currItemOffset + 6, nextItemOffset); + long itemTime = Long.parseLong(item);*/ + long itemTime = MathUtil.str2Long(datas, currItemOffset + 6, nextItemOffset); + System.out.println("TIME : " + itemTime); + if (itemTime < 0 || itemTime > 2000000000000000L) { + } + sqlInfo.setTime(itemTime); + + //user@host + currItemOffset = offsets[1]; + nextItemOffset = offsets[2]; + String item = substring(datas, currItemOffset + 12, nextItemOffset); + System.out.println("user@host : " + item); +// sqlInfo.setUserHost(item); + + //db + currItemOffset = offsets[2]; + nextItemOffset = offsets[3]; + int dbOffset = currItemOffset + 5; + int dbLen = nextItemOffset - dbOffset; + long dbHash = FnvHash.fnv1a_64(datas, dbOffset, nextItemOffset); + String db = dbSymbols.addSymbol(datas, dbOffset, dbLen, dbHash); + + // String db = substring(datas, currItemOffset + 5, nextItemOffset); + System.out.println("db : " + db); + if (dbLen > 0 && SqlUtil.filterDbs.indexOf(db) != -1) { +// sqlInfo.setNotValiDB(true); + } else { + } + + //table_name + currItemOffset = offsets[3]; + nextItemOffset = offsets[4]; + int tsqlPos = currItemOffset + 13; + int idx2 = indexOf_nReturn(datas, tsqlPos); + String table = substring(datas, tsqlPos, idx2); + sql = substring(datas, idx2 + 1, nextItemOffset); + System.out.println("table : " + table + " : " + sql); + + int totalLen = sql.length(); + if (totalLen < 9 || + totalLen >= 8000) { +// sqlInfo.setParseRes(0); + } else { + } + + //query_time + currItemOffset = offsets[4]; + nextItemOffset = offsets[5]; + int rtBound = Math.min(nextItemOffset - currItemOffset, 24); + double itemRt = MathUtil.str2Double(datas, currItemOffset + 13, currItemOffset + rtBound); + sqlInfo.setQueryTime(itemRt); + + //lock_time + currItemOffset = offsets[5]; + nextItemOffset = offsets[6]; + int lockTimeBound = Math.min(nextItemOffset - currItemOffset, 23); + double itemLockTime = MathUtil.str2Double(datas, currItemOffset + 12, currItemOffset + lockTimeBound); + sqlInfo.setLockTime(itemLockTime); + + //rows_sent + currItemOffset = offsets[6]; + nextItemOffset = offsets[7]; + long itemRowsSent = MathUtil.str2Long(datas, currItemOffset + 12, nextItemOffset); + if (itemRowsSent < 0 || itemRowsSent > 1000000000) { + } +// sqlInfo.setRowsSent(itemRowsSent); + + //rows_examined + currItemOffset = offsets[7]; + nextItemOffset = offsets[8]; + long itemRowsExam = MathUtil.str2Long(datas, currItemOffset + 16, nextItemOffset); + if (itemRowsExam < 0 || itemRowsExam > 1000000000) { + } +// sqlInfo.setRowsExamined(itemRowsExam); + + //rows_affected + currItemOffset = offsets[8]; + nextItemOffset = offsets[9]; + long itemRowsAffected = MathUtil.str2Long(datas, currItemOffset + 16, nextItemOffset); + if (itemRowsAffected < 0 || itemRowsAffected > 1000000000) { + } + sqlInfo.setRowsAffected(itemRowsAffected); + + //innodb_pages_read + currItemOffset = offsets[9]; + nextItemOffset = offsets[10]; + long itemPageRead = MathUtil.str2Long(datas, currItemOffset + 20, nextItemOffset); + if (itemPageRead < 0 || itemPageRead > 1000000000) { + } + sqlInfo.setInnodbPagesRead(itemPageRead); + + //innodb_pages_io_read + currItemOffset = offsets[10]; + nextItemOffset = offsets[11]; + long itemPageIORead = MathUtil.str2Long(datas, currItemOffset + 23, nextItemOffset); + if (itemPageIORead < 0 || itemPageIORead > 1000000000) { + } +// sqlInfo.setInnodbPagesIoRead(itemPageIORead); + // currItemOffset = nextItemOffset; + + /*nextItemOffset = datas.indexOf("\n#", currItemOffset + 1); + if (nextItemOffset >= end) { + return null; + } + itemEnd = nextItemOffset == -1 ? end : nextItemOffset; + item = datas.substring(currItemOffset + 1, itemEnd); + sqlInfo.setId(Long.parseLong(item.trim().substring(4))); + num++;*/ + // sqlInfo.setId(0); + } + + } + + System.out.println(System.currentTimeMillis() - start); + } + + static class SqlInfo { + private long innodbPagesRead; + private long time; + private double queryTime; + private double lockTime; + public long rowsAffected; + + public long getInnodbPagesRead() { + return innodbPagesRead; + } + + public void setInnodbPagesRead(long innodbPagesRead) { + this.innodbPagesRead = innodbPagesRead; + } + + public long getTime() { + return time; + } + + public void setTime(long time) { + this.time = time; + } + + public void setQueryTime(double queryTime) { + this.queryTime = queryTime; + } + + public void setLockTime(double lockTime) { + this.lockTime = lockTime; + } + + public void setRowsAffected(long rowsAffected) { + this.rowsAffected = rowsAffected; + } + } + + static class MathUtil { + public static long str2Long(byte[] data, int start, int end) { + long value = 0; + for (int i = start; i < end; ++i) { + byte ch = data[i]; + if (ch == '.') break; + int digit = data[i] - '0'; + value = value * 10 + digit; + } + return value; + } + + public static double str2Double(byte[] data,int start,int end) { + long value = 0; + long power = 0; + for (int i = start; i < end; ++i) { + byte ch = data[i]; + if (ch == '.') { + power = 1; + continue; + } + int digit = ch - '0'; + value = value * 10 + digit; + power *= 10; + } + double doubleValue = (double) value; + if (power == 0) { + return doubleValue; + } else { + return doubleValue / power; + } + } + } + + static class SqlUtil { + + public static Set filterDb = new HashSet(); + + private static int[] orders = new int[]{2, 3, 0, 1}; + + static { + filterDb.add("DRC"); + filterDb.add("INFORMATION_SCHEMA"); + filterDb.add("INNODB_MEMCACHE"); + filterDb.add("MYSQL"); + filterDb.add("PERFORMANCE_SCHEMA"); + filterDb.add("RECYCLE_BIN"); + filterDb.add("ROCKSDB"); + filterDb.add("TEST"); + filterDb.add("DRC".toLowerCase()); + filterDb.add("INFORMATION_SCHEMA".toLowerCase()); + filterDb.add("INNODB_MEMCACHE".toLowerCase()); + filterDb.add("MYSQL".toLowerCase()); + filterDb.add("PERFORMANCE_SCHEMA".toLowerCase()); + filterDb.add("RECYCLE_BIN".toLowerCase()); + filterDb.add("ROCKSDB".toLowerCase()); + filterDb.add("TEST".toLowerCase()); + } + + public static final String filterDbs = org.apache.commons.lang3.StringUtils.join(SqlUtil.filterDb, ","); + } +} \ No newline at end of file diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/select/MySqlSelectTest_60_firstComment.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/select/MySqlSelectTest_60_firstComment.java new file mode 100644 index 0000000000..1189c3524e --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/select/MySqlSelectTest_60_firstComment.java @@ -0,0 +1,67 @@ +/* + * 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 com.alibaba.druid.sql.MysqlTest; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.parser.SQLParserFeature; +import com.alibaba.druid.sql.parser.SQLParserUtils; +import com.alibaba.druid.sql.parser.SQLStatementParser; +import com.alibaba.druid.sql.visitor.SchemaStatVisitor; +import com.alibaba.druid.util.JdbcConstants; + +import java.util.List; + +public class MySqlSelectTest_60_firstComment extends MysqlTest { + + public void test_0() throws Exception { + String sql = "/* xxx * xxxx */SELECT * from t where t ! = 1"; + + System.out.println(sql); + + SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, JdbcConstants.MYSQL, SQLParserFeature.OptimizedForParameterized); + List statementList = parser.parseStatementList(); + SQLStatement stmt = statementList.get(0); + + assertEquals(1, statementList.size()); + + SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.MYSQL); + stmt.accept(visitor); + { + String output = SQLUtils.toMySqlString(stmt); + assertEquals("SELECT *\n" + + "FROM t\n" + + "WHERE t != 1", // + output); + } + { + String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION); + assertEquals("select *\n" + + "from t\n" + + "where t != 1", // + output); + } + + { + String output = SQLUtils.toMySqlString(stmt, new SQLUtils.FormatOption(true, true, true)); + assertEquals("SELECT *\n" + + "FROM t\n" + + "WHERE t != ?", // + output); + } + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/select/MySqlSelectTest_61_firstComment_2.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/select/MySqlSelectTest_61_firstComment_2.java new file mode 100644 index 0000000000..d9bc3a9e77 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/select/MySqlSelectTest_61_firstComment_2.java @@ -0,0 +1,67 @@ +/* + * 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 com.alibaba.druid.sql.MysqlTest; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.parser.SQLParserFeature; +import com.alibaba.druid.sql.parser.SQLParserUtils; +import com.alibaba.druid.sql.parser.SQLStatementParser; +import com.alibaba.druid.sql.visitor.SchemaStatVisitor; +import com.alibaba.druid.util.JdbcConstants; + +import java.util.List; + +public class MySqlSelectTest_61_firstComment_2 extends MysqlTest { + + public void test_0() throws Exception { + String sql = "/* xxx * xxxx */ SELECT * from t where t ! = 1"; + + System.out.println(sql); + + SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, JdbcConstants.MYSQL, SQLParserFeature.OptimizedForParameterized); + List statementList = parser.parseStatementList(); + SQLStatement stmt = statementList.get(0); + + assertEquals(1, statementList.size()); + + SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.MYSQL); + stmt.accept(visitor); + { + String output = SQLUtils.toMySqlString(stmt); + assertEquals("SELECT *\n" + + "FROM t\n" + + "WHERE t != 1", // + output); + } + { + String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION); + assertEquals("select *\n" + + "from t\n" + + "where t != 1", // + output); + } + + { + String output = SQLUtils.toMySqlString(stmt, new SQLUtils.FormatOption(true, true, true)); + assertEquals("SELECT *\n" + + "FROM t\n" + + "WHERE t != ?", // + output); + } + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/select/MySqlSelectTest_62_optimized.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/select/MySqlSelectTest_62_optimized.java new file mode 100644 index 0000000000..2d92692e29 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/select/MySqlSelectTest_62_optimized.java @@ -0,0 +1,67 @@ +/* + * 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 com.alibaba.druid.sql.MysqlTest; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.parser.SQLParserFeature; +import com.alibaba.druid.sql.parser.SQLParserUtils; +import com.alibaba.druid.sql.parser.SQLStatementParser; +import com.alibaba.druid.sql.visitor.SchemaStatVisitor; +import com.alibaba.druid.util.JdbcConstants; + +import java.util.List; + +public class MySqlSelectTest_62_optimized extends MysqlTest { + + public void test_0() throws Exception { + String sql = "SELECT * from t where t ! = 1"; + + System.out.println(sql); + + SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, JdbcConstants.MYSQL, SQLParserFeature.OptimizedForParameterized); + List statementList = parser.parseStatementList(); + SQLStatement stmt = statementList.get(0); + + assertEquals(1, statementList.size()); + + SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.MYSQL); + stmt.accept(visitor); + { + String output = SQLUtils.toMySqlString(stmt); + assertEquals("SELECT *\n" + + "FROM t\n" + + "WHERE t != 1", // + output); + } + { + String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION); + assertEquals("select *\n" + + "from t\n" + + "where t != 1", // + output); + } + + { + String output = SQLUtils.toMySqlString(stmt, new SQLUtils.FormatOption(true, true, true)); + assertEquals("SELECT *\n" + + "FROM t\n" + + "WHERE t != ?", // + output); + } + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest57.java b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest57.java new file mode 100644 index 0000000000..bd1edb5cf3 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest57.java @@ -0,0 +1,74 @@ +/* + * 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.postgresql.select; + +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 junit.framework.TestCase; + +import java.util.List; + +public class PGSelectTest57 extends TestCase { + private final String dbType = JdbcConstants.POSTGRESQL; + + public void test_0() throws Exception { + String sql = "SELECT ts#, file#, block#, cols, IFNULL(size$, -1), pctfree$, pctused$\n" + + " , initrans, maxtrans, hashkeys, func, extind\n" + + " , avgchn, IFNULL(degree, 1)\n" + + " , IFNULL(instances, 1)\n" + + " , IFNULL(flags, 0)\n" + + " , IFNULL(spare1, 0)\n" + + "FROM clu$\n" + + "WHERE obj# ='633'"; + + List stmtList = SQLUtils.parseStatements(sql, dbType); + SQLStatement stmt = stmtList.get(0); + + assertEquals("SELECT ts#, file#, block#, cols\n" + + "\t, IFNULL(size$, -1), pctfree$\n" + + "\t, pctused$, initrans, maxtrans, hashkeys, func\n" + + "\t, extind, avgchn, IFNULL(degree, 1)\n" + + "\t, IFNULL(instances, 1)\n" + + "\t, IFNULL(flags, 0)\n" + + "\t, IFNULL(spare1, 0)\n" + + "FROM clu$\n" + + "WHERE obj# = '633'", SQLUtils.toPGString(stmt)); + + assertEquals("select ts#, file#, block#, cols\n" + + "\t, IFNULL(size$, -1), pctfree$\n" + + "\t, pctused$, initrans, maxtrans, hashkeys, func\n" + + "\t, extind, avgchn, IFNULL(degree, 1)\n" + + "\t, IFNULL(instances, 1)\n" + + "\t, IFNULL(flags, 0)\n" + + "\t, IFNULL(spare1, 0)\n" + + "from clu$\n" + + "where obj# = '633'", SQLUtils.toPGString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION)); + + assertEquals(1, stmtList.size()); + + SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(dbType); + stmt.accept(visitor); + +// System.out.println("Tables : " + visitor.getTables()); +// System.out.println("fields : " + visitor.getColumns()); +// System.out.println("coditions : " + visitor.getConditions()); + + assertEquals(18, visitor.getColumns().size()); + assertEquals(1, visitor.getTables().size()); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/transform/datatype/oracle2pg/Oracle2MySql_method_sys_guid.java b/src/test/java/com/alibaba/druid/bvt/sql/transform/datatype/oracle2pg/Oracle2MySql_method_sys_guid.java new file mode 100644 index 0000000000..a9f8bf1469 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/transform/datatype/oracle2pg/Oracle2MySql_method_sys_guid.java @@ -0,0 +1,18 @@ +package com.alibaba.druid.bvt.sql.transform.datatype.oracle2pg; + +import com.alibaba.druid.sql.SQLTransformUtils; +import com.alibaba.druid.sql.ast.SQLDataType; +import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr; +import com.alibaba.druid.sql.parser.SQLParserUtils; +import com.alibaba.druid.util.JdbcConstants; +import junit.framework.TestCase; + +public class Oracle2MySql_method_sys_guid extends TestCase { + public void test_oracle2pg_int_1() throws Exception { + String sql = "sys_guid()"; + SQLMethodInvokeExpr expr = (SQLMethodInvokeExpr) SQLParserUtils.createExprParser(sql, JdbcConstants.ORACLE).expr(); + SQLExpr targetExpr = SQLTransformUtils.transformOracleToPostgresql(expr); + assertEquals("uuid_generate_v4()", targetExpr.toString()); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/transform/datatype/oracle2pg/Oracle2PG_DataTypeTest_chars.java b/src/test/java/com/alibaba/druid/bvt/sql/transform/datatype/oracle2pg/Oracle2PG_DataTypeTest_chars.java index d34cb48bf2..b2654e6be5 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/transform/datatype/oracle2pg/Oracle2PG_DataTypeTest_chars.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/transform/datatype/oracle2pg/Oracle2PG_DataTypeTest_chars.java @@ -98,4 +98,12 @@ public class Oracle2PG_DataTypeTest_chars extends TestCase { SQLDataType pgDataType = SQLTransformUtils.transformOracleToPostgresql(dataType); assertEquals("TEXT", pgDataType.toString()); } + + + public void test_oracle2pg_bfile() throws Exception { + String sql = "bfile"; + SQLDataType dataType = SQLParserUtils.createExprParser(sql, JdbcConstants.ORACLE).parseDataType(); + SQLDataType pgDataType = SQLTransformUtils.transformOracleToPostgresql(dataType); + assertEquals("VARCHAR(255)", pgDataType.toString()); + } } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/transform/datatype/oracle2pg/Oracle2PG_DataTypeTest_double.java b/src/test/java/com/alibaba/druid/bvt/sql/transform/datatype/oracle2pg/Oracle2PG_DataTypeTest_double.java index 162570d79e..ce445f6bd3 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/transform/datatype/oracle2pg/Oracle2PG_DataTypeTest_double.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/transform/datatype/oracle2pg/Oracle2PG_DataTypeTest_double.java @@ -48,5 +48,13 @@ public class Oracle2PG_DataTypeTest_double extends TestCase { SQLDataType pgDataType = SQLTransformUtils.transformOracleToPostgresql(dataType); assertEquals("DOUBLE PRECISION", pgDataType.toString()); } + + + public void test_oracle2pg_number_star() throws Exception { + String sql = "number(*)"; + SQLDataType dataType = SQLParserUtils.createExprParser(sql, JdbcConstants.ORACLE).parseDataType(); + SQLDataType pgDataType = SQLTransformUtils.transformOracleToPostgresql(dataType); + assertEquals("DOUBLE PRECISION", pgDataType.toString()); + } } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/transform/datatype/oracle2pg/Oracle2PG_DataTypeTest_number_int.java b/src/test/java/com/alibaba/druid/bvt/sql/transform/datatype/oracle2pg/Oracle2PG_DataTypeTest_number_int.java index 3220ad8d65..72cc249780 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/transform/datatype/oracle2pg/Oracle2PG_DataTypeTest_number_int.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/transform/datatype/oracle2pg/Oracle2PG_DataTypeTest_number_int.java @@ -158,7 +158,7 @@ public class Oracle2PG_DataTypeTest_number_int extends TestCase { String sql = "number(*)"; SQLDataType dataType = SQLParserUtils.createExprParser(sql, JdbcConstants.ORACLE).parseDataType(); SQLDataType pgDataType = SQLTransformUtils.transformOracleToPostgresql(dataType); - assertEquals("BIGINT", pgDataType.toString()); + assertEquals("DOUBLE PRECISION", pgDataType.toString()); } public void test_oracle2pg_int_21() throws Exception {