diff --git a/src/main/java/com/alibaba/druid/sql/SQLTransformUtils.java b/src/main/java/com/alibaba/druid/sql/SQLTransformUtils.java index 075cd291fd..a274caab5d 100644 --- a/src/main/java/com/alibaba/druid/sql/SQLTransformUtils.java +++ b/src/main/java/com/alibaba/druid/sql/SQLTransformUtils.java @@ -605,7 +605,7 @@ public class SQLTransformUtils { || nameHash == FnvHash.Constants.NCLOB || nameHash == FnvHash.Constants.LONG) { argumentns.clear(); - dataType = new SQLCharacterDataType("TEXT"); + dataType = new SQLCharacterDataType("text"); } else if (nameHash == FnvHash.Constants.XMLTYPE) { dataType = new SQLDataTypeImpl("xml"); diff --git a/src/main/java/com/alibaba/druid/sql/SQLUtils.java b/src/main/java/com/alibaba/druid/sql/SQLUtils.java index b4e3f7c4d8..f94e68a3fd 100644 --- a/src/main/java/com/alibaba/druid/sql/SQLUtils.java +++ b/src/main/java/com/alibaba/druid/sql/SQLUtils.java @@ -25,6 +25,8 @@ import com.alibaba.druid.sql.dialect.db2.visitor.DB2OutputVisitor; import com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor; import com.alibaba.druid.sql.dialect.h2.visitor.H2OutputVisitor; import com.alibaba.druid.sql.dialect.h2.visitor.H2SchemaStatVisitor; +import com.alibaba.druid.sql.dialect.hive.visitor.HiveOutputVisitor; +import com.alibaba.druid.sql.dialect.hive.visitor.HiveSchemaStatVisitor; import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor; import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor; import com.alibaba.druid.sql.dialect.odps.visitor.OdpsOutputVisitor; @@ -130,10 +132,18 @@ public class SQLUtils { return format(sql, JdbcConstants.ODPS); } + public static String formatHive(String sql) { + return format(sql, JdbcConstants.HIVE); + } + public static String formatOdps(String sql, FormatOption option) { return format(sql, JdbcConstants.ODPS, option); } + public static String formatHive(String sql, FormatOption option) { + return format(sql, JdbcConstants.HIVE, option); + } + public static String formatSQLServer(String sql) { return format(sql, JdbcConstants.SQL_SERVER); } @@ -389,6 +399,14 @@ public class SQLUtils { return new H2OutputVisitor(out); } + if (JdbcConstants.HIVE.equals(dbType)) { + return new HiveOutputVisitor(out); + } + + if (JdbcConstants.ELASTIC_SEARCH.equals(dbType)) { + return new MySqlOutputVisitor(out); + } + return new SQLASTOutputVisitor(out, dbType); } @@ -427,6 +445,14 @@ public class SQLUtils { return new H2SchemaStatVisitor(); } + if (JdbcConstants.HIVE.equals(dbType)) { + return new HiveSchemaStatVisitor(); + } + + if (JdbcConstants.ELASTIC_SEARCH.equals(dbType)) { + return new MySqlSchemaStatVisitor(); + } + return new SchemaStatVisitor(); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/hive/parser/HiveExprParser.java b/src/main/java/com/alibaba/druid/sql/dialect/hive/parser/HiveExprParser.java new file mode 100644 index 0000000000..19e1161412 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/hive/parser/HiveExprParser.java @@ -0,0 +1,57 @@ +/* + * 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.sql.dialect.hive.parser; + +import com.alibaba.druid.sql.parser.Lexer; +import com.alibaba.druid.sql.parser.SQLExprParser; +import com.alibaba.druid.sql.parser.SQLParserFeature; +import com.alibaba.druid.util.FnvHash; + +import java.util.Arrays; + +public class HiveExprParser extends SQLExprParser { + private final static String[] AGGREGATE_FUNCTIONS; + private final static long[] AGGREGATE_FUNCTIONS_CODES; + + static { + String[] strings = { "AVG", "COUNT", "MAX", "MIN", "STDDEV", "SUM", "ROW_NUMBER", + "ROWNUMBER" }; + + AGGREGATE_FUNCTIONS_CODES = FnvHash.fnv1a_64_lower(strings, true); + AGGREGATE_FUNCTIONS = new String[AGGREGATE_FUNCTIONS_CODES.length]; + for (String str : strings) { + long hash = FnvHash.fnv1a_64_lower(str); + int index = Arrays.binarySearch(AGGREGATE_FUNCTIONS_CODES, hash); + AGGREGATE_FUNCTIONS[index] = str; + } + } + + public HiveExprParser(String sql){ + this(new HiveLexer(sql)); + this.lexer.nextToken(); + } + + public HiveExprParser(String sql, SQLParserFeature... features){ + this(new HiveLexer(sql, features)); + this.lexer.nextToken(); + } + + public HiveExprParser(Lexer lexer){ + super(lexer); + this.aggregateFunctions = AGGREGATE_FUNCTIONS; + this.aggregateFunctionHashCodes = AGGREGATE_FUNCTIONS_CODES; + } +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/hive/parser/HiveLexer.java b/src/main/java/com/alibaba/druid/sql/dialect/hive/parser/HiveLexer.java new file mode 100644 index 0000000000..be21946266 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/hive/parser/HiveLexer.java @@ -0,0 +1,58 @@ +/* + * 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.sql.dialect.hive.parser; + +import com.alibaba.druid.sql.parser.Keywords; +import com.alibaba.druid.sql.parser.Lexer; +import com.alibaba.druid.sql.parser.SQLParserFeature; +import com.alibaba.druid.sql.parser.Token; + +import java.util.HashMap; +import java.util.Map; + +public class HiveLexer extends Lexer { + public final static Keywords DEFAULT_HIVE_KEYWORDS; + + static { + Map map = new HashMap(); + + map.putAll(Keywords.DEFAULT_KEYWORDS.getKeywords()); + + map.put("OF", Token.OF); + map.put("CONCAT", Token.CONCAT); + map.put("CONTINUE", Token.CONTINUE); + map.put("MERGE", Token.MERGE); + map.put("USING", Token.USING); + + map.put("ROW", Token.ROW); + map.put("LIMIT", Token.LIMIT); + + DEFAULT_HIVE_KEYWORDS = new Keywords(map); + } + + public HiveLexer(String input){ + super(input); + super.keywods = DEFAULT_HIVE_KEYWORDS; + } + + public HiveLexer(String input, SQLParserFeature... features){ + super(input); + super.keywods = DEFAULT_HIVE_KEYWORDS; + for (SQLParserFeature feature : features) { + config(feature, true); + } + } +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/hive/parser/HiveSelectParser.java b/src/main/java/com/alibaba/druid/sql/dialect/hive/parser/HiveSelectParser.java new file mode 100644 index 0000000000..f97cd8608b --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/hive/parser/HiveSelectParser.java @@ -0,0 +1,39 @@ +/* + * 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.sql.dialect.hive.parser; + +import com.alibaba.druid.sql.parser.SQLExprParser; +import com.alibaba.druid.sql.parser.SQLSelectListCache; +import com.alibaba.druid.sql.parser.SQLSelectParser; + +public class HiveSelectParser extends SQLSelectParser { + + public HiveSelectParser(SQLExprParser exprParser){ + super(exprParser); + } + + public HiveSelectParser(SQLExprParser exprParser, SQLSelectListCache selectListCache){ + super(exprParser, selectListCache); + } + + public HiveSelectParser(String sql){ + this(new HiveExprParser(sql)); + } + + protected SQLExprParser createExprParser() { + return new HiveExprParser(lexer); + } +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/hive/parser/HiveStatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/hive/parser/HiveStatementParser.java new file mode 100644 index 0000000000..f6df697308 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/hive/parser/HiveStatementParser.java @@ -0,0 +1,78 @@ +/* + * 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.sql.dialect.hive.parser; + +import com.alibaba.druid.sql.ast.SQLName; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.ast.expr.SQLQueryExpr; +import com.alibaba.druid.sql.ast.statement.SQLReplaceStatement; +import com.alibaba.druid.sql.ast.statement.SQLSelect; +import com.alibaba.druid.sql.parser.Lexer; +import com.alibaba.druid.sql.parser.SQLParserFeature; +import com.alibaba.druid.sql.parser.SQLStatementParser; +import com.alibaba.druid.sql.parser.Token; +import com.alibaba.druid.util.JdbcConstants; + +public class HiveStatementParser extends SQLStatementParser { + public HiveStatementParser(String sql) { + super (new HiveExprParser(sql)); + } + + public HiveStatementParser(String sql, SQLParserFeature... features) { + super (new HiveExprParser(sql, features)); + } + + public HiveStatementParser(Lexer lexer){ + super(new HiveExprParser(lexer)); + } + + public HiveSelectParser createSQLSelectParser() { + return new HiveSelectParser(this.exprParser, selectListCache); + } + + public SQLStatement parseMerge() { + accept(Token.MERGE); + accept(Token.INTO); + + SQLReplaceStatement stmt = new SQLReplaceStatement(); + stmt.setDbType(JdbcConstants.HIVE); + + SQLName tableName = exprParser.name(); + stmt.setTableName(tableName); + + if (lexer.token() == Token.KEY) { + lexer.nextToken(); + accept(Token.LPAREN); + this.exprParser.exprList(stmt.getColumns(), stmt); + accept(Token.RPAREN); + } + + if (lexer.token() == Token.VALUES || lexer.identifierEquals("VALUE")) { + lexer.nextToken(); + + parseValueClause(stmt.getValuesList(), 0, stmt); + } else if (lexer.token() == Token.SELECT) { + SQLQueryExpr queryExpr = (SQLQueryExpr) this.exprParser.expr(); + stmt.setQuery(queryExpr); + } else if (lexer.token() == Token.LPAREN) { + SQLSelect select = this.createSQLSelectParser().select(); + SQLQueryExpr queryExpr = new SQLQueryExpr(select); + stmt.setQuery(queryExpr); + } + + return stmt; + } +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/hive/visitor/HiveASTVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/hive/visitor/HiveASTVisitor.java new file mode 100644 index 0000000000..4dc4be3b71 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/hive/visitor/HiveASTVisitor.java @@ -0,0 +1,21 @@ +/* + * 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.sql.dialect.hive.visitor; + +import com.alibaba.druid.sql.visitor.SQLASTVisitor; + +public interface HiveASTVisitor extends SQLASTVisitor { +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/hive/visitor/HiveASTVisitorAdapter.java b/src/main/java/com/alibaba/druid/sql/dialect/hive/visitor/HiveASTVisitorAdapter.java new file mode 100644 index 0000000000..619393d6cb --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/hive/visitor/HiveASTVisitorAdapter.java @@ -0,0 +1,21 @@ +/* + * 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.sql.dialect.hive.visitor; + +import com.alibaba.druid.sql.visitor.SQLASTVisitorAdapter; + +public class HiveASTVisitorAdapter extends SQLASTVisitorAdapter implements HiveASTVisitor { +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/hive/visitor/HiveOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/hive/visitor/HiveOutputVisitor.java new file mode 100644 index 0000000000..63fea168aa --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/hive/visitor/HiveOutputVisitor.java @@ -0,0 +1,35 @@ +/* + * 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.sql.dialect.hive.visitor; + +import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor; + +import java.util.List; + +public class HiveOutputVisitor extends SQLASTOutputVisitor implements HiveASTVisitor { + public HiveOutputVisitor(Appendable appender) { + super(appender); + } + + public HiveOutputVisitor(Appendable appender, String dbType) { + super(appender, dbType); + } + + public HiveOutputVisitor(Appendable appender, boolean parameterized) { + super(appender, parameterized); + } + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/hive/visitor/HiveSchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/hive/visitor/HiveSchemaStatVisitor.java new file mode 100644 index 0000000000..c716f317d8 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/hive/visitor/HiveSchemaStatVisitor.java @@ -0,0 +1,21 @@ +/* + * 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.sql.dialect.hive.visitor; + +import com.alibaba.druid.sql.visitor.SchemaStatVisitor; + +public class HiveSchemaStatVisitor extends SchemaStatVisitor { +} 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 24deb7db26..c10aab4f91 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 @@ -83,8 +83,50 @@ public class MySqlExprParser extends SQLExprParser { } public MySqlExprParser(String sql, SQLParserFeature... features){ - this(new MySqlLexer(sql, features)); + super(new MySqlLexer(sql, features), JdbcConstants.MYSQL); + this.aggregateFunctions = AGGREGATE_FUNCTIONS; + this.aggregateFunctionHashCodes = AGGREGATE_FUNCTIONS_CODES; + if (sql.length() > 6) { + char c0 = sql.charAt(0); + char c1 = sql.charAt(1); + char c2 = sql.charAt(2); + char c3 = sql.charAt(3); + char c4 = sql.charAt(4); + char c5 = sql.charAt(5); + char c6 = sql.charAt(6); + + if (c0 == 'S' && c1 == 'E' && c2 == 'L' && c3 == 'E' && c4 == 'C' && c5 == 'T' && c6 == ' ') { + lexer.reset(6, ' ', Token.SELECT); + return; + } + + if (c0 == 's' && c1 == 'e' && c2 == 'l' && c3 == 'e' && c4 == 'c' && c5 == 't' && c6 == ' ') { + lexer.reset(6, ' ', Token.SELECT); + return; + } + + if (c0 == 'I' && c1 == 'N' && c2 == 'S' && c3 == 'E' && c4 == 'R' && c5 == 'T' && c6 == ' ') { + lexer.reset(6, ' ', Token.INSERT); + return; + } + + if (c0 == 'i' && c1 == 'n' && c2 == 's' && c3 == 'e' && c4 == 'r' && c5 == 't' && c6 == ' ') { + lexer.reset(6, ' ', Token.INSERT); + return; + } + + if (c0 == 'U' && c1 == 'P' && c2 == 'D' && c3 == 'A' && c4 == 'T' && c5 == 'E' && c6 == ' ') { + lexer.reset(6, ' ', Token.UPDATE); + return; + } + + if (c0 == 'u' && c1 == 'p' && c2 == 'd' && c3 == 'a' && c4 == 't' && c5 == 'e' && c6 == ' ') { + lexer.reset(6, ' ', Token.UPDATE); + return; + } + } this.lexer.nextToken(); + } public MySqlExprParser(String sql, boolean keepComments){ 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 a2aa0106d7..c64a82eced 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 @@ -74,7 +74,10 @@ public class MySqlLexer extends Lexer { } public MySqlLexer(String input, SQLParserFeature... features){ - this(input, true, true); + super(input, true); + this.keepComments = true; + super.keywods = DEFAULT_MYSQL_KEYWORDS; + for (SQLParserFeature feature : features) { config(feature, true); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlSelectParser.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlSelectParser.java index dad82adf7d..b30e9e62d7 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlSelectParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlSelectParser.java @@ -58,7 +58,7 @@ public class MySqlSelectParser extends SQLSelectParser { return; } - lexer.nextToken(); + lexer.nextTokenIdent(); if (lexer.token() == Token.UPDATE) { // taobao returning to urgly syntax updateStmt = this.parseUpdateStatment(); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java index 891c409708..00da79f638 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java @@ -2199,7 +2199,7 @@ public class MySqlStatementParser extends SQLStatementParser { columnSize++; if (lexer.token() == Token.COMMA) { - lexer.nextToken(); + lexer.nextTokenIdent(); continue; } @@ -2256,7 +2256,27 @@ public class MySqlStatementParser extends SQLStatementParser { accept(Token.KEY); accept(Token.UPDATE); - exprParser.exprList(insertStatement.getDuplicateKeyUpdate(), insertStatement); + List duplicateKeyUpdate = insertStatement.getDuplicateKeyUpdate(); + for (;;) { + SQLName name = this.exprParser.name(); + accept(Token.EQ); + SQLExpr value; + try { + value = this.exprParser.expr(); + } catch (EOFParserException e) { + throw new ParserException("EOF, " + name + "=", e); + } + + SQLBinaryOpExpr assignment = new SQLBinaryOpExpr(name, SQLBinaryOperator.Equality, value); + assignment.setParent(insertStatement); + duplicateKeyUpdate.add(assignment); + + if (lexer.token() == Token.COMMA) { + lexer.nextTokenIdent(); + continue; + } + break; + } } return insertStatement; diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java index a123ae1742..843a757418 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java @@ -942,10 +942,10 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV protected void printValuesList(List valuesList) { - if (this.parameterized) { + if (this.parameterized && valuesList.size() > 0) { print0(ucase ? "VALUES " : "values "); this.indentCount++; - valuesList.get(0).accept(this); + visit(valuesList.get(0)); this.indentCount--; if (valuesList.size() > 1) { this.incrementReplaceCunt(); 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 4be1be60a8..461028d28c 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/Lexer.java +++ b/src/main/java/com/alibaba/druid/sql/parser/Lexer.java @@ -214,9 +214,8 @@ public class Lexer { this.skipComment = skipComment; this.text = input; - this.pos = -1; - - scanChar(); + this.pos = 0; + ch = charAt(pos); } public Lexer(char[] input, int inputLength, boolean skipComment){ @@ -419,6 +418,12 @@ public class Lexer { } } + if (ch == ')') { + scanChar(); + token = Token.RPAREN; + return; + } + if (isFirstIdentifierChar(ch)) { scanIdentifier(); return; @@ -487,6 +492,25 @@ public class Lexer { nextToken(); } + public final void nextTokenIdent() { + while (ch == ' ') { + scanChar(); + } + + if (isFirstIdentifierChar(ch)) { + scanIdentifier(); + return; + } + + if (ch == ')') { + scanChar(); + token = RPAREN; + return; + } + + nextToken(); + } + public final void nextToken() { startPos = pos; bufPos = 0; 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 5f96eb7263..44f86acc53 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java @@ -362,6 +362,9 @@ public class SQLExprParser extends SQLParser { } SQLVariantRefExpr varRefExpr = new SQLVariantRefExpr(varName); + if (varName.startsWith(":")) { + varRefExpr.setIndex(lexer.nextVarIndex()); + } if (varRefExpr.getName().equals("@") && lexer.token == Token.LITERAL_CHARS) { varRefExpr.setName("@'" + lexer.stringVal() + "'"); lexer.nextToken(); @@ -1575,11 +1578,12 @@ public class SQLExprParser extends SQLParser { public final SQLExpr inRest(SQLExpr expr) { if (lexer.token == Token.IN) { - lexer.nextToken(); + lexer.nextTokenLParen(); SQLInListExpr inListExpr = new SQLInListExpr(expr); + List targetList = inListExpr.getTargetList(); if (lexer.token == Token.LPAREN) { - lexer.nextToken(); + lexer.nextTokenValue(); if (lexer.token == Token.WITH) { SQLSelect select = this.createSelectParser().select(); @@ -1589,7 +1593,6 @@ public class SQLExprParser extends SQLParser { return queryExpr; } - List targetList = inListExpr.getTargetList(); for (;;) { SQLExpr item = this.expr(); item.setParent(inListExpr); @@ -1605,13 +1608,13 @@ public class SQLExprParser extends SQLParser { } else { SQLExpr itemExpr = primary(); itemExpr.setParent(inListExpr); - inListExpr.getTargetList().add(itemExpr); + targetList.add(itemExpr); } expr = inListExpr; - if (inListExpr.getTargetList().size() == 1) { - SQLExpr targetExpr = inListExpr.getTargetList().get(0); + if (targetList.size() == 1) { + SQLExpr targetExpr = targetList.get(0); if (targetExpr instanceof SQLQueryExpr) { SQLInSubQueryExpr inSubQueryExpr = new SQLInSubQueryExpr(); inSubQueryExpr.setExpr(inListExpr.getExpr()); @@ -2629,7 +2632,7 @@ public class SQLExprParser extends SQLParser { token = lexer.token; if (token == Token.DOT) { - lexer.nextToken(); + lexer.nextTokenIdent(); String name; long name_hash_lower; diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLParserUtils.java b/src/main/java/com/alibaba/druid/sql/parser/SQLParserUtils.java index 33a0c63289..9aa909e8e0 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLParserUtils.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLParserUtils.java @@ -21,6 +21,7 @@ import com.alibaba.druid.sql.dialect.db2.parser.DB2ExprParser; import com.alibaba.druid.sql.dialect.db2.parser.DB2Lexer; import com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser; import com.alibaba.druid.sql.dialect.h2.parser.H2StatementParser; +import com.alibaba.druid.sql.dialect.hive.parser.HiveStatementParser; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock; import com.alibaba.druid.sql.dialect.mysql.parser.MySqlExprParser; import com.alibaba.druid.sql.dialect.mysql.parser.MySqlLexer; @@ -105,6 +106,14 @@ public class SQLParserUtils { return new PhoenixStatementParser(sql); } + if (JdbcUtils.HIVE.equals(dbType)) { + return new HiveStatementParser(sql); + } + + if (JdbcUtils.ELASTIC_SEARCH.equals(dbType)) { + return new MySqlStatementParser(sql); + } + return new SQLStatementParser(sql, dbType); } 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 e2245ea6b8..54dc202a1a 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java @@ -18,8 +18,7 @@ package com.alibaba.druid.sql.parser; import java.util.List; import com.alibaba.druid.sql.ast.*; -import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; -import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr; +import com.alibaba.druid.sql.ast.expr.*; import com.alibaba.druid.sql.ast.statement.*; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlOrderingExpr; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock; @@ -318,13 +317,47 @@ public class SQLSelectParser extends SQLParser { public void parseWhere(SQLSelectQueryBlock queryBlock) { if (lexer.token == Token.WHERE) { - lexer.nextToken(); + lexer.nextTokenIdent(); List beforeComments = null; if (lexer.hasComment() && lexer.isKeepComments()) { beforeComments = lexer.readAndResetComments(); } - SQLExpr where = expr(); + + SQLExpr where; + + if (lexer.token == Token.IDENTIFIER) { + String ident = lexer.stringVal(); + long hash_lower = lexer.hash_lower(); + lexer.nextTokenEq(); + + SQLExpr identExpr = new SQLIdentifierExpr(ident, hash_lower); + + if (lexer.token == Token.DOT) { + identExpr = this.exprParser.primaryRest(identExpr); + } + + if (lexer.token == Token.EQ) { + SQLExpr rightExp; + + lexer.nextToken(); + try { + rightExp = this.exprParser.bitOr(); + } catch (EOFParserException e) { + throw new ParserException("EOF, " + ident + "=", e); + } + + where = new SQLBinaryOpExpr(identExpr, SQLBinaryOperator.Equality, rightExp, dbType); + where = this.exprParser.andRest(where); + where = this.exprParser.orRest(where); + } else { + identExpr = this.exprParser.primaryRest(identExpr); + where = this.exprParser.exprRest(identExpr); + } + } else { + where = this.exprParser.expr(); + } +// where = this.exprParser.expr(); if (beforeComments != null) { where.addBeforeComment(beforeComments); 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 8788813441..41e80533ef 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java @@ -2433,7 +2433,26 @@ public class SQLStatementParser extends SQLParser { } public SQLStatement parseStatement() { - return parseStatement(false); + if (lexer.token == Token.SELECT) { + return this.parseSelect(); + } + + if (lexer.token == Token.INSERT) { + return this.parseInsert(); + } + + + if (lexer.token == Token.UPDATE) { + return this.parseUpdateStatement(); + } + + if (lexer.token == Token.DELETE) { + return this.parseDeleteStatement(); + } + + List list = new ArrayList(1); + this.parseStatementList(list, 1, null); + return list.get(0); } /** 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 0a0da89e16..8b6c78e1b4 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/ParameterizedOutputVisitorUtils.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/ParameterizedOutputVisitorUtils.java @@ -119,6 +119,10 @@ public class ParameterizedOutputVisitorUtils { return new PhoenixOutputVisitor(out, true); } + if (JdbcUtils.ELASTIC_SEARCH.equals(dbType)) { + return new MySqlOutputVisitor(out, true); + } + return new SQLASTOutputVisitor(out, true); } } 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 01703ffef5..11575c0adc 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -1897,9 +1897,6 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet protected void printTableSourceExpr(SQLExpr expr) { if (exportTables) { - if (expr instanceof SQLIdentifierExpr) { - - } addTable(expr.toString()); } diff --git a/src/main/java/com/alibaba/druid/util/JdbcConstants.java b/src/main/java/com/alibaba/druid/util/JdbcConstants.java index d69183847f..94b93dd3e8 100644 --- a/src/main/java/com/alibaba/druid/util/JdbcConstants.java +++ b/src/main/java/com/alibaba/druid/util/JdbcConstants.java @@ -105,4 +105,7 @@ public interface JdbcConstants { public static final String ALIYUN_DRDS = "aliyun_drds"; public static final String PRESTO = "presto"; + + public static final String ELASTIC_SEARCH = "elastic_search"; + String ELASTIC_SEARCH_DRIVER = "com.alibaba.xdriver.elastic.jdbc.ElasticDriver"; } diff --git a/src/main/java/com/alibaba/druid/util/JdbcUtils.java b/src/main/java/com/alibaba/druid/util/JdbcUtils.java index 2d76e80c26..7f4e959989 100644 --- a/src/main/java/com/alibaba/druid/util/JdbcUtils.java +++ b/src/main/java/com/alibaba/druid/util/JdbcUtils.java @@ -462,6 +462,8 @@ public final class JdbcUtils implements JdbcConstants { return JdbcConstants.PHOENIX_DRIVER; } else if (rawUrl.startsWith("jdbc:kylin:")) { return JdbcConstants.KYLIN_DRIVER; + } else if (rawUrl.startsWith("jdbc:elastic:")) { + return JdbcConstants.ELASTIC_SEARCH_DRIVER; } else { throw new SQLException("unkow jdbc driver : " + rawUrl); } @@ -547,6 +549,8 @@ public final class JdbcUtils implements JdbcConstants { return HIVE; } else if (rawUrl.startsWith("jdbc:phoenix:")) { return PHOENIX; + } else if (rawUrl.startsWith("jdbc:elastic:")) { + return ELASTIC_SEARCH; } else { return null; } diff --git a/src/main/java/com/alibaba/druid/wall/WallConfig.java b/src/main/java/com/alibaba/druid/wall/WallConfig.java index 23897d026c..3eb61754de 100644 --- a/src/main/java/com/alibaba/druid/wall/WallConfig.java +++ b/src/main/java/com/alibaba/druid/wall/WallConfig.java @@ -864,6 +864,18 @@ public class WallConfig implements WallConfigMBean { } } } + { + Boolean propertyValue = getBoolean(properties, "druid.wall.updateWhereNoneCheck"); + if (propertyValue != null) { + this.setUpdateWhereNoneCheck(propertyValue); + } + } + { + Boolean propertyValue = getBoolean(properties, "druid.wall.deleteWhereNoneCheck"); + if (propertyValue != null) { + this.setDeleteWhereNoneCheck(propertyValue); + } + } } public void addUpdateCheckCoumns(String columnInfo) { diff --git a/src/test/java/com/alibaba/druid/bvt/sql/elastic/Elastic_StatFilter_merge_0.java b/src/test/java/com/alibaba/druid/bvt/sql/elastic/Elastic_StatFilter_merge_0.java new file mode 100644 index 0000000000..fcf1f656b1 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/elastic/Elastic_StatFilter_merge_0.java @@ -0,0 +1,42 @@ +package com.alibaba.druid.bvt.sql.elastic; + +import com.alibaba.druid.filter.stat.MergeStatFilter; +import com.alibaba.druid.filter.stat.StatFilter; +import com.alibaba.druid.util.JdbcConstants; +import junit.framework.TestCase; + +public class Elastic_StatFilter_merge_0 extends TestCase { + public void test_for_stat_merge() throws Exception { + String sql = "/* ///9fe39e72/ */SELECT fkc1.fkc_order_id, fkc1.out_order_id, fkc1.seller_nick, fkc1.buyer_nick, fkc1.seller_id, fkc1.buyer_id, fkc1.auction_id, fkc1.auction_title, fkc1.auction_price, fkc1.buy_amount, fkc1.fkc_type, fkc1.sub_fkc_type, fkc1.fail_reason, fkc1.pay_status, fkc1.logistics_status, fkc1.out_trade_status, fkc1.snap_path, fkc1.gmt_create, fkc1.status, ifnull(fkc1.buyer_rate_status, 4) AS buyer_rate_status, ifnull(fkc1.seller_rate_status, 4) AS seller_rate_status, fkc1.auction_pict_url, fkc1.seller_memo, fkc1.buyer_memo, fkc1.seller_flag, fkc1.buyer_flag, fkc1.buyer_message_path, fkc1.refund_status, fkc1.attributes, fkc1.attributes_cc, fkc1.gmt_modified, fkc1.ip, fkc1.end_time, fkc1.pay_time, fkc1.is_main, fkc1.is_detail, fkc1.point_rate, fkc1.parent_id, fkc1.adjust_fee, fkc1.discount_fee, fkc1.refund_fee, fkc1.confirm_paid_fee, fkc1.cod_status, fkc1.trade_tag, fkc1.shop_id, fkc1.options, fkc1.ignore_sold_quantity, fkc1.from_group, fkc1.gmt_create_tc FROM (SELECT fkc_order_id FROM tc_fkc_order AS tc_fkc_order IGNORE INDEX (ind_fkc_order_status, idx_sid_bt_st_im) WHERE is_main = 1 AND (fkc_type = 2700 OR fkc_type = 200 OR fkc_type = 10000 OR fkc_type = 610 OR fkc_type = 600 OR fkc_type = 300 OR fkc_type = 100 OR fkc_type = 500 OR fkc_type = 900 OR fkc_type = 620 OR fkc_type = 630 OR fkc_type = 650 OR fkc_type = 1000 OR fkc_type = 1001 OR fkc_type = 710 OR fkc_type = 1200 OR fkc_type = 1201 OR fkc_type = 1500 OR fkc_type = 1600 OR fkc_type = 2000 OR fkc_type = 2400) AND seller_id = 2169996291 AND (sub_fkc_type = 1 OR sub_fkc_type = 901 OR sub_fkc_type = 801 OR sub_fkc_type = 701 OR sub_fkc_type = 601 OR sub_fkc_type = 2) AND status = 0 AND gmt_create >= DATE_FORMAT('2017-04-22 00:00:00', '%Y-%m-%d %T') AND gmt_create <= DATE_FORMAT('2017-05-07 23:59:59', '%Y-%m-%d %T') AND from_group = 0 ORDER BY gmt_create DESC LIMIT 900, 100) AS fkc2, tc_fkc_order AS fkc1 WHERE fkc2.fkc_order_id = 1"; + StatFilter filter = new MergeStatFilter(); + filter.setDbType(JdbcConstants.ELASTIC_SEARCH); + String mergedSql = filter.mergeSql(sql, JdbcConstants.ELASTIC_SEARCH); + assertEquals("SELECT fkc1.fkc_order_id, fkc1.out_order_id, fkc1.seller_nick, fkc1.buyer_nick, fkc1.seller_id\n" + + "\t, fkc1.buyer_id, fkc1.auction_id, fkc1.auction_title, fkc1.auction_price, fkc1.buy_amount\n" + + "\t, fkc1.fkc_type, fkc1.sub_fkc_type, fkc1.fail_reason, fkc1.pay_status, fkc1.logistics_status\n" + + "\t, fkc1.out_trade_status, fkc1.snap_path, fkc1.gmt_create, fkc1.status\n" + + "\t, ifnull(fkc1.buyer_rate_status, ?) AS buyer_rate_status\n" + + "\t, ifnull(fkc1.seller_rate_status, ?) AS seller_rate_status, fkc1.auction_pict_url\n" + + "\t, fkc1.seller_memo, fkc1.buyer_memo, fkc1.seller_flag, fkc1.buyer_flag, fkc1.buyer_message_path\n" + + "\t, fkc1.refund_status, fkc1.attributes, fkc1.attributes_cc, fkc1.gmt_modified, fkc1.ip\n" + + "\t, fkc1.end_time, fkc1.pay_time, fkc1.is_main, fkc1.is_detail, fkc1.point_rate\n" + + "\t, fkc1.parent_id, fkc1.adjust_fee, fkc1.discount_fee, fkc1.refund_fee, fkc1.confirm_paid_fee\n" + + "\t, fkc1.cod_status, fkc1.trade_tag, fkc1.shop_id, fkc1.options, fkc1.ignore_sold_quantity\n" + + "\t, fkc1.from_group, fkc1.gmt_create_tc\n" + + "FROM (\n" + + "\tSELECT fkc_order_id\n" + + "\tFROM tc_fkc_order tc_fkc_order IGNORE INDEX (ind_fkc_order_status, idx_sid_bt_st_im)\n" + + "\tWHERE is_main = ?\n" + + "\t\tAND (fkc_type = ?)\n" + + "\t\tAND seller_id = ?\n" + + "\t\tAND (sub_fkc_type = ?)\n" + + "\t\tAND status = ?\n" + + "\t\tAND gmt_create >= DATE_FORMAT(?, '%Y-%m-%d %T')\n" + + "\t\tAND gmt_create <= DATE_FORMAT(?, '%Y-%m-%d %T')\n" + + "\t\tAND from_group = ?\n" + + "\tORDER BY gmt_create DESC\n" + + "\tLIMIT ?, ?\n" + + ") fkc2, tc_fkc_order fkc1\n" + + "WHERE fkc2.fkc_order_id = ?", mergedSql); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveSelectTest_0.java b/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveSelectTest_0.java new file mode 100644 index 0000000000..da834559ee --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveSelectTest_0.java @@ -0,0 +1,47 @@ +package com.alibaba.druid.bvt.sql.hive; + +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.visitor.SchemaStatVisitor; +import com.alibaba.druid.stat.TableStat; +import com.alibaba.druid.util.JdbcConstants; +import junit.framework.TestCase; +import org.junit.Assert; + +import java.util.List; + +public class HiveSelectTest_0 extends TestCase { + public void test_select() throws Exception { + String sql = "SELECT page_views.*\n" + + "FROM page_views\n" + + "WHERE page_views.date >= '2008-03-01' AND page_views.date <= '2008-03-31'";// + Assert.assertEquals("SELECT page_views.*\n" + + "FROM page_views\n" + + "WHERE page_views.date >= '2008-03-01'\n" + + "\tAND page_views.date <= '2008-03-31'", SQLUtils.formatHive(sql)); + Assert.assertEquals("select page_views.*\n" + + "from page_views\n" + + "where page_views.date >= '2008-03-01'\n" + + "\tand page_views.date <= '2008-03-31'", SQLUtils.formatHive(sql, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION)); + + List statementList = SQLUtils.parseStatements(sql, JdbcConstants.HIVE); + SQLStatement stmt = statementList.get(0); + + Assert.assertEquals(1, statementList.size()); + + SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE); + stmt.accept(visitor); + +// System.out.println("Tables : " + visitor.getTables()); +// System.out.println("fields : " + visitor.getColumns()); +// System.out.println("coditions : " + visitor.getConditions()); +// System.out.println("orderBy : " + visitor.getOrderByColumns()); + + Assert.assertEquals(1, visitor.getTables().size()); + Assert.assertEquals(2, visitor.getColumns().size()); + Assert.assertEquals(2, visitor.getConditions().size()); + + Assert.assertTrue(visitor.containsColumn("page_views", "date")); + Assert.assertTrue(visitor.containsColumn("page_views", "*")); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveSelectTest_1_limit.java b/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveSelectTest_1_limit.java new file mode 100644 index 0000000000..78db7a00b0 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/hive/HiveSelectTest_1_limit.java @@ -0,0 +1,44 @@ +package com.alibaba.druid.bvt.sql.hive; + +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 org.junit.Assert; + +import java.util.List; + +public class HiveSelectTest_1_limit extends TestCase { + public void test_select() throws Exception { + String sql = "SELECT * FROM customers ORDER BY create_date LIMIT 2,5";// + assertEquals("SELECT *\n" + + "FROM customers\n" + + "ORDER BY create_date\n" + + "LIMIT 2, 5", SQLUtils.formatHive(sql)); + assertEquals("select *\n" + + "from customers\n" + + "order by create_date\n" + + "limit 2, 5", SQLUtils.formatHive(sql, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION)); + + List statementList = SQLUtils.parseStatements(sql, JdbcConstants.HIVE); + SQLStatement stmt = statementList.get(0); + + assertEquals(1, statementList.size()); + + SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.HIVE); + stmt.accept(visitor); + +// System.out.println("Tables : " + visitor.getTables()); +// System.out.println("fields : " + visitor.getColumns()); +// System.out.println("coditions : " + visitor.getConditions()); +// System.out.println("orderBy : " + visitor.getOrderByColumns()); + + assertEquals(1, visitor.getTables().size()); + assertEquals(2, visitor.getColumns().size()); + assertEquals(0, visitor.getConditions().size()); + + assertTrue(visitor.containsColumn("customers", "create_date")); + assertTrue(visitor.containsColumn("customers", "*")); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/MySqlParameterizedOutputVisitorTest_52_schema.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/MySqlParameterizedOutputVisitorTest_52_schema.java index 316cca7fc2..ad552636cf 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/MySqlParameterizedOutputVisitorTest_52_schema.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/MySqlParameterizedOutputVisitorTest_52_schema.java @@ -17,9 +17,9 @@ import java.util.List; public class MySqlParameterizedOutputVisitorTest_52_schema extends TestCase { public void test_for_parameterize() throws Exception { final String dbType = JdbcConstants.MYSQL; - String sql = "UPDATE `buyer_0158`.xc_yy_order\n" + - "SET `ALIPAY_BUYER_ID` = ?, `GMT_MODIFIED` = ?\n" + - "WHERE `PAY_ORDER_ID` = ?"; + String sql = "UPDATE `buyer_0158`.xc_yy_order_1082\n" + + "SET `ALIPAY_BUYER_ID` = 1025, `GMT_MODIFIED` = 'aaaa'\n" + + "WHERE `PAY_ORDER_ID` = 'kkk'"; SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType); List stmtList = parser.parseStatementList(); diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/MySqlParameterizedOutputVisitorTest_55.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/MySqlParameterizedOutputVisitorTest_55.java new file mode 100644 index 0000000000..6bca15e530 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/MySqlParameterizedOutputVisitorTest_55.java @@ -0,0 +1,72 @@ +package com.alibaba.druid.bvt.sql.mysql.param; + +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.parser.SQLParserUtils; +import com.alibaba.druid.sql.parser.SQLStatementParser; +import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor; +import com.alibaba.druid.util.JdbcConstants; +import junit.framework.TestCase; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by wenshao on 16/8/23. + */ +public class MySqlParameterizedOutputVisitorTest_55 extends TestCase { + public void test_for_parameterize() throws Exception { + final String dbType = JdbcConstants.MYSQL; + String sql = "/* ///9fe39e72/ */SELECT fck1.fck_order_id, fck1.out_order_id, fck1.seller_nick, fck1.buyer_nick, fck1.seller_id, fck1.buyer_id, fck1.auction_id, fck1.auction_title, fck1.auction_price, fck1.buy_amount, fck1.fck_type, fck1.sub_fck_type, fck1.fail_reason, fck1.pay_status, fck1.logistics_status, fck1.out_trade_status, fck1.snap_path, fck1.gmt_create, fck1.status, ifnull(fck1.buyer_rate_status, 4) AS buyer_rate_status, ifnull(fck1.seller_rate_status, 4) AS seller_rate_status, fck1.auction_pict_url, fck1.seller_memo, fck1.buyer_memo, fck1.seller_flag, fck1.buyer_flag, fck1.buyer_message_path, fck1.refund_status, fck1.attributes, fck1.attributes_cc, fck1.gmt_modified, fck1.ip, fck1.end_time, fck1.pay_time, fck1.is_main, fck1.is_detail, fck1.point_rate, fck1.parent_id, fck1.adjust_fee, fck1.discount_fee, fck1.refund_fee, fck1.confirm_paid_fee, fck1.cod_status, fck1.trade_tag, fck1.shop_id, fck1.options, fck1.ignore_sold_quantity, fck1.from_group, fck1.gmt_create_tc FROM (SELECT fck_order_id FROM tc_fck_order AS tc_fck_order IGNORE INDEX (ind_fck_order_status, idx_sid_bt_st_im) WHERE is_main = 1 AND (fck_type = 2700 OR fck_type = 200 OR fck_type = 10000 OR fck_type = 610 OR fck_type = 600 OR fck_type = 300 OR fck_type = 100 OR fck_type = 500 OR fck_type = 900 OR fck_type = 620 OR fck_type = 630 OR fck_type = 650 OR fck_type = 1000 OR fck_type = 1001 OR fck_type = 710 OR fck_type = 1200 OR fck_type = 1201 OR fck_type = 1500 OR fck_type = 1600 OR fck_type = 2000 OR fck_type = 2400) AND seller_id = 2169996291 AND (sub_fck_type = 1 OR sub_fck_type = 901 OR sub_fck_type = 801 OR sub_fck_type = 701 OR sub_fck_type = 601 OR sub_fck_type = 2) AND status = 0 AND gmt_create >= DATE_FORMAT('2017-04-22 00:00:00', '%Y-%m-%d %T') AND gmt_create <= DATE_FORMAT('2017-05-07 23:59:59', '%Y-%m-%d %T') AND from_group = 0 ORDER BY gmt_create DESC LIMIT 900, 100) AS fck2, tc_fck_order AS fck1 WHERE fck2.fck_order_id = fck1.fck_order_id"; + + SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType); + List stmtList = parser.parseStatementList(); + SQLStatement statement = stmtList.get(0); + + StringBuilder out = new StringBuilder(); + SQLASTOutputVisitor visitor = SQLUtils.createOutputVisitor(out, JdbcConstants.MYSQL); + List parameters = new ArrayList(); + visitor.setParameterized(true); + visitor.setParameterizedMergeInList(true); + visitor.setParameters(parameters); + /*visitor.setPrettyFormat(false);*/ + statement.accept(visitor); + /* JSONArray array = new JSONArray(); + for(String table : visitor.getTables()){ + array.add(table.replaceAll("`","")); + }*/ + + String psql = out.toString(); + + System.out.println(psql); + + + assertEquals("SELECT fck1.fck_order_id, fck1.out_order_id, fck1.seller_nick, fck1.buyer_nick, fck1.seller_id\n" + + "\t, fck1.buyer_id, fck1.auction_id, fck1.auction_title, fck1.auction_price, fck1.buy_amount\n" + + "\t, fck1.fck_type, fck1.sub_fck_type, fck1.fail_reason, fck1.pay_status, fck1.logistics_status\n" + + "\t, fck1.out_trade_status, fck1.snap_path, fck1.gmt_create, fck1.status\n" + + "\t, ifnull(fck1.buyer_rate_status, ?) AS buyer_rate_status\n" + + "\t, ifnull(fck1.seller_rate_status, ?) AS seller_rate_status, fck1.auction_pict_url\n" + + "\t, fck1.seller_memo, fck1.buyer_memo, fck1.seller_flag, fck1.buyer_flag, fck1.buyer_message_path\n" + + "\t, fck1.refund_status, fck1.attributes, fck1.attributes_cc, fck1.gmt_modified, fck1.ip\n" + + "\t, fck1.end_time, fck1.pay_time, fck1.is_main, fck1.is_detail, fck1.point_rate\n" + + "\t, fck1.parent_id, fck1.adjust_fee, fck1.discount_fee, fck1.refund_fee, fck1.confirm_paid_fee\n" + + "\t, fck1.cod_status, fck1.trade_tag, fck1.shop_id, fck1.options, fck1.ignore_sold_quantity\n" + + "\t, fck1.from_group, fck1.gmt_create_tc\n" + + "FROM (\n" + + "\tSELECT fck_order_id\n" + + "\tFROM tc_fck_order tc_fck_order IGNORE INDEX (ind_fck_order_status, idx_sid_bt_st_im)\n" + + "\tWHERE is_main = ?\n" + + "\t\tAND (fck_type = ?)\n" + + "\t\tAND seller_id = ?\n" + + "\t\tAND (sub_fck_type = ?)\n" + + "\t\tAND status = ?\n" + + "\t\tAND gmt_create >= DATE_FORMAT(?, '%Y-%m-%d %T')\n" + + "\t\tAND gmt_create <= DATE_FORMAT(?, '%Y-%m-%d %T')\n" + + "\t\tAND from_group = ?\n" + + "\tORDER BY gmt_create DESC\n" + + "\tLIMIT ?, ?\n" + + ") fck2, tc_fck_order fck1\n" + + "WHERE fck2.fck_order_id = fck1.fck_order_id", psql); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/visitor/OracleParameterizedOutputVisitorTest_01.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/visitor/OracleParameterizedOutputVisitorTest_01.java new file mode 100644 index 0000000000..30ec7710ef --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/visitor/OracleParameterizedOutputVisitorTest_01.java @@ -0,0 +1,60 @@ +package com.alibaba.druid.bvt.sql.oracle.visitor; + +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.parser.SQLParserUtils; +import com.alibaba.druid.sql.parser.SQLStatementParser; +import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor; +import com.alibaba.druid.util.JdbcConstants; +import com.sun.org.apache.xerces.internal.xs.datatypes.ObjectList; +import junit.framework.TestCase; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Created by wenshao on 16/8/23. + */ +public class OracleParameterizedOutputVisitorTest_01 extends TestCase { + public void test_for_parameterize() throws Exception { + String sql = "SELECT dd.synonym_name table_name,'EAIREP' as schema_name, aa.num_rows,bb.comments description,to_char(cc.created,'YYYY-MM-DD HH24:MI:SS') createTime,to_char(cc.last_ddl_time,'YYYY-MM-DD HH24:MI:SS') last_ddl_time, 'SYNONYM' table_type ,lower(aa.owner || '.' || aa.table_name) ref_info\n" + + " from dba_synonyms dd,\n" + + " dba_objects cc,\n" + + " dba_tables aa\n" + + " left join dba_tab_comments bb\n" + + " on aa.owner = bb.owner\n" + + " and aa.table_name = bb.table_name\n" + + " where aa.owner=cc.owner\n" + + " and aa.table_name=cc.object_name\n" + + " and cc.subobject_name is null\n" + + " and cc.object_type='TABLE'\n" + + " and aa.owner = dd.table_owner\n" + + " and aa.table_name = dd.table_name and dd.owner = :1 "; + List parameters = new ArrayList(); + parameters.add("EAIREP"); + List stmts = SQLUtils.parseStatements(sql, JdbcConstants.ORACLE); + String tempResult = SQLUtils.toSQLString(stmts, com.alibaba.druid.util.JdbcConstants.ORACLE, parameters); + assertEquals("SELECT dd.synonym_name AS table_name, 'EAIREP' AS schema_name, aa.num_rows, bb.comments AS description\n" + + "\t, to_char(cc.created, 'YYYY-MM-DD HH24:MI:SS') AS createTime\n" + + "\t, to_char(cc.last_ddl_time, 'YYYY-MM-DD HH24:MI:SS') AS last_ddl_time, 'SYNONYM' AS table_type\n" + + "\t, lower(aa.owner || '.' || aa.table_name) AS ref_info\n" + + "FROM dba_synonyms dd, dba_objects cc, dba_tables aa\n" + + "\tLEFT JOIN dba_tab_comments bb ON aa.owner = bb.owner\n" + + "AND aa.table_name = bb.table_name \n" + + "WHERE aa.owner = cc.owner\n" + + "\tAND aa.table_name = cc.object_name\n" + + "\tAND cc.subobject_name IS NULL\n" + + "\tAND cc.object_type = 'TABLE'\n" + + "\tAND aa.owner = dd.table_owner\n" + + "\tAND aa.table_name = dd.table_name\n" + + "\tAND dd.owner = 'EAIREP'", tempResult); + } + + static void f() { + String ip = ""; + String port = ""; + String[] ins = new String[]{ip, "_", port}; + + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/transform/Oracle2PG_DataTypeTest_chars.java b/src/test/java/com/alibaba/druid/bvt/sql/transform/Oracle2PG_DataTypeTest_chars.java index c608ca287b..b400ede13d 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/transform/Oracle2PG_DataTypeTest_chars.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/transform/Oracle2PG_DataTypeTest_chars.java @@ -83,4 +83,19 @@ public class Oracle2PG_DataTypeTest_chars extends TestCase { SQLDataType pgDataType = SQLTransformUtils.transformOracleToPostgresql(dataType); assertEquals("varchar(255)", pgDataType.toString()); } + + public void test_oracle2pg_varchar2_8000() throws Exception { + String sql = "varchar2(8000)"; + SQLDataType dataType = SQLParserUtils.createExprParser(sql, JdbcConstants.ORACLE).parseDataType(); + SQLDataType pgDataType = SQLTransformUtils.transformOracleToPostgresql(dataType); + assertEquals("text", pgDataType.toString()); + } + + + public void test_oracle2pg_varchar2_10000() throws Exception { + String sql = "varchar2(10000)"; + SQLDataType dataType = SQLParserUtils.createExprParser(sql, JdbcConstants.ORACLE).parseDataType(); + SQLDataType pgDataType = SQLTransformUtils.transformOracleToPostgresql(dataType); + assertEquals("text", pgDataType.toString()); + } } diff --git a/src/test/java/com/alibaba/druid/bvt/utils/JdbcUtils_driver.java b/src/test/java/com/alibaba/druid/bvt/utils/JdbcUtils_driver.java index 03160f6df9..541d085002 100644 --- a/src/test/java/com/alibaba/druid/bvt/utils/JdbcUtils_driver.java +++ b/src/test/java/com/alibaba/druid/bvt/utils/JdbcUtils_driver.java @@ -46,4 +46,19 @@ public class JdbcUtils_driver extends TestCase { String dbType = JdbcUtils.getDbType(jdbcUrl, "net.sf.log4jdbc.sql.jdbcapi.DriverSpy"); assertEquals("not support log4jdbc mysql, url like jdbc:log4jdbc:derby:...", JdbcConstants.DERBY, dbType); } + + public void test_log4jdbc_es() throws Exception { + assertEquals(JdbcConstants.ELASTIC_SEARCH + , JdbcUtils.getDbType("jdbc:elastic://100.69.202.4:9300/tcbuyer?cluster.name=refund_cluster", null)); + } + + public void test_log4jdbc_es_1() throws Exception { + assertEquals(JdbcConstants.ELASTIC_SEARCH + , JdbcUtils.getDbType("jdbc:elastic://100.69.202.4:9300/tcbuyer?cluster.name=refund_cluster", "com.alibaba.xdriver.elastic.jdbc.ElasticDriver")); + } + + public void test_log4jdbc_es_driver() throws Exception { + assertEquals(JdbcConstants.ELASTIC_SEARCH_DRIVER + , JdbcUtils.getDriverClassName("jdbc:elastic://100.69.202.4:9300/tcbuyer?cluster.name=refund_cluster")); + } }