diff --git a/pom.xml b/pom.xml
index 04f6b37989..2104fe36d0 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,7 +3,7 @@
4.0.0
com.alibaba
druid
- 1.1.9-preview_1
+ 1.1.11-preview_1
jar
druid
diff --git a/src/main/java/com/alibaba/druid/VERSION.java b/src/main/java/com/alibaba/druid/VERSION.java
index 00d4063dec..5411c788d8 100644
--- a/src/main/java/com/alibaba/druid/VERSION.java
+++ b/src/main/java/com/alibaba/druid/VERSION.java
@@ -19,7 +19,7 @@ public final class VERSION {
public final static int MajorVersion = 1;
public final static int MinorVersion = 1;
- public final static int RevisionVersion = 10;
+ public final static int RevisionVersion = 11;
public static String getVersionNumber() {
return VERSION.MajorVersion + "." + VERSION.MinorVersion + "." + VERSION.RevisionVersion;
diff --git a/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java b/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java
index 51314d1ad1..dad199045d 100644
--- a/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java
+++ b/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java
@@ -1632,7 +1632,8 @@ public abstract class DruidAbstractDataSource extends WrapperAdapter implements
validateConnection(conn);
validatedNanos = System.nanoTime();
-
+
+ setFailContinuous(false);
setCreateError(null);
} catch (SQLException ex) {
setCreateError(ex);
diff --git a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java
index 3d15d97bfd..95eba5d89e 100644
--- a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java
+++ b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java
@@ -2294,7 +2294,6 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
try {
physicalConnection = createPhysicalConnection();
- setFailContinuous(false);
} catch (OutOfMemoryError e) {
LOG.error("create connection OutOfMemoryError, out memory. ", e);
@@ -2466,7 +2465,6 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
try {
connection = createPhysicalConnection();
- setFailContinuous(false);
} catch (SQLException e) {
LOG.error("create connection SQLException, url: " + jdbcUrl + ", errorCode " + e.getErrorCode()
+ ", state " + e.getSQLState(), e);
diff --git a/src/main/java/com/alibaba/druid/sql/ast/SQLExprImpl.java b/src/main/java/com/alibaba/druid/sql/ast/SQLExprImpl.java
index 8aefcdc237..4843db4fe1 100644
--- a/src/main/java/com/alibaba/druid/sql/ast/SQLExprImpl.java
+++ b/src/main/java/com/alibaba/druid/sql/ast/SQLExprImpl.java
@@ -17,6 +17,9 @@ package com.alibaba.druid.sql.ast;
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
+import java.util.Collections;
+import java.util.List;
+
public abstract class SQLExprImpl extends SQLObjectImpl implements SQLExpr {
public SQLExprImpl(){
@@ -27,11 +30,16 @@ public abstract class SQLExprImpl extends SQLObjectImpl implements SQLExpr {
public abstract int hashCode();
- public abstract SQLExpr clone();
+ public SQLExpr clone() {
+ throw new UnsupportedOperationException();
+ }
public SQLDataType computeDataType() {
return null;
}
+ public List getChildren() {
+ return Collections.emptyList();
+ }
}
diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLAggregateExpr.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLAggregateExpr.java
index 8fa9e7f99d..3f1ce6798e 100644
--- a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLAggregateExpr.java
+++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLAggregateExpr.java
@@ -35,6 +35,7 @@ public class SQLAggregateExpr extends SQLExprImpl implements Serializable, SQLRe
protected SQLAggregateOption option;
protected final List arguments = new ArrayList();
protected SQLKeep keep;
+ protected SQLExpr filter;
protected SQLOver over;
protected SQLName overRef;
protected SQLOrderBy withinGroup;
@@ -186,6 +187,7 @@ public class SQLAggregateExpr extends SQLExprImpl implements Serializable, SQLRe
if (option != that.option) return false;
if (arguments != null ? !arguments.equals(that.arguments) : that.arguments != null) return false;
if (keep != null ? !keep.equals(that.keep) : that.keep != null) return false;
+ if (filter != null ? !filter.equals(that.filter) : that.filter != null) return false;
if (over != null ? !over.equals(that.over) : that.over != null) return false;
if (overRef != null ? !overRef.equals(that.overRef) : that.overRef != null) return false;
if (withinGroup != null ? !withinGroup.equals(that.withinGroup) : that.withinGroup != null) return false;
@@ -199,6 +201,7 @@ public class SQLAggregateExpr extends SQLExprImpl implements Serializable, SQLRe
result = 31 * result + (option != null ? option.hashCode() : 0);
result = 31 * result + (arguments != null ? arguments.hashCode() : 0);
result = 31 * result + (keep != null ? keep.hashCode() : 0);
+ result = 31 * result + (filter != null ? filter.hashCode() : 0);
result = 31 * result + (over != null ? over.hashCode() : 0);
result = 31 * result + (overRef != null ? overRef.hashCode() : 0);
result = 31 * result + (withinGroup != null ? withinGroup.hashCode() : 0);
@@ -219,6 +222,10 @@ public class SQLAggregateExpr extends SQLExprImpl implements Serializable, SQLRe
x.setKeep(keep.clone());
}
+ if (filter != null) {
+ x.setFilter(filter.clone());
+ }
+
if (over != null) {
x.setOver(over.clone());
}
@@ -236,6 +243,17 @@ public class SQLAggregateExpr extends SQLExprImpl implements Serializable, SQLRe
return x;
}
+ public SQLExpr getFilter() {
+ return filter;
+ }
+
+ public void setFilter(SQLExpr x) {
+ if (x != null) {
+ x.setParent(this);
+ }
+ this.filter = x;
+ }
+
public SQLDataType computeDataType() {
long hash = methodNameHashCod64();
@@ -277,6 +295,11 @@ public class SQLAggregateExpr extends SQLExprImpl implements Serializable, SQLRe
return true;
}
+ if (filter == expr) {
+ this.filter = target;
+ target.setParent(this);
+ }
+
return false;
}
}
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 8cd4d02ddb..bb868c9e0a 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
@@ -431,6 +431,21 @@ public class SQLColumnDefinition extends SQLObjectImpl implements SQLTableElemen
return false;
}
+ public boolean isPrimaryKey() {
+ for (SQLColumnConstraint constraint : constraints) {
+ if (constraint instanceof SQLColumnPrimaryKey) {
+ return true;
+ }
+ }
+
+ if (parent instanceof SQLCreateTableStatement) {
+ return ((SQLCreateTableStatement) parent)
+ .isPrimaryColumn(nameHashCode64());
+ }
+
+ return false;
+ }
+
public String toString() {
return SQLUtils.toSQLString(this, dbType);
}
diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateTableStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateTableStatement.java
index 5b8fec750b..aef97407ce 100644
--- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateTableStatement.java
+++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateTableStatement.java
@@ -1107,4 +1107,12 @@ public class SQLCreateTableStatement extends SQLStatementImpl implements SQLDDLS
this.rowFormat = x;
}
+ public boolean isPrimaryColumn(long columnNameHash) {
+ SQLPrimaryKey pk = this.findPrimaryKey();
+ if (pk == null) {
+ return false;
+ }
+
+ return pk.containsColumn(columnNameHash);
+ }
}
diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDumpStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDumpStatement.java
new file mode 100644
index 0000000000..f555699836
--- /dev/null
+++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDumpStatement.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 1999-2018 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.ast.statement;
+
+import com.alibaba.druid.sql.ast.SQLExpr;
+import com.alibaba.druid.sql.ast.SQLStatementImpl;
+import com.alibaba.druid.sql.visitor.SQLASTVisitor;
+
+public class SQLDumpStatement extends SQLStatementImpl {
+ private boolean overwrite;
+ private SQLExprTableSource into;
+
+ private SQLSelect select;
+
+ public SQLDumpStatement() {
+
+ }
+
+ public SQLSelect getSelect() {
+ return select;
+ }
+
+ public void setSelect(SQLSelect x) {
+ if (x != null) {
+ x.setParent(this);
+ }
+
+ this.select = x;
+ }
+
+ public SQLExprTableSource getInto() {
+ return into;
+ }
+
+ public void setInto(SQLExpr x) {
+ if (x == null) {
+ return;
+ }
+
+ setInto(new SQLExprTableSource(x));
+ }
+
+ public void setInto(SQLExprTableSource x) {
+ if (x != null) {
+ x.setParent(this);
+ }
+
+ this.into = x;
+ }
+
+ public boolean isOverwrite() {
+ return overwrite;
+ }
+
+ public void setOverwrite(boolean overwrite) {
+ this.overwrite = overwrite;
+ }
+
+ @Override
+ protected void accept0(SQLASTVisitor visitor) {
+ if (visitor.visit(this)) {
+ if (into != null) {
+ into.accept(visitor);
+ }
+
+ if (select != null) {
+ select.accept(visitor);
+ }
+ }
+ visitor.endVisit(this);
+ }
+}
diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLUnique.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLUnique.java
index d34fa6e202..68e2da2b37 100644
--- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLUnique.java
+++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLUnique.java
@@ -73,6 +73,18 @@ public class SQLUnique extends SQLConstraintImpl implements SQLUniqueConstraint,
return false;
}
+ public boolean containsColumn(long columnNameHash) {
+ for (SQLSelectOrderByItem item : columns) {
+ SQLExpr expr = item.getExpr();
+ if (expr instanceof SQLIdentifierExpr) {
+ if (((SQLIdentifierExpr) expr).nameHashCode64() == columnNameHash) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
public void cloneTo(SQLUnique x) {
super.cloneTo(x);
diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLUniqueConstraint.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLUniqueConstraint.java
index 1d14b9efa9..73906a9460 100644
--- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLUniqueConstraint.java
+++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLUniqueConstraint.java
@@ -24,4 +24,5 @@ public interface SQLUniqueConstraint extends SQLConstraint {
List getColumns();
boolean containsColumn(String column);
+ boolean containsColumn(long columnNameHash);
}
diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlLockTableStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlLockTableStatement.java
index 0e3ddbe078..724e14ce08 100644
--- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlLockTableStatement.java
+++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlLockTableStatement.java
@@ -15,47 +15,22 @@
*/
package com.alibaba.druid.sql.dialect.mysql.ast.statement;
+import java.util.ArrayList;
import java.util.List;
import com.alibaba.druid.sql.ast.SQLCommentHint;
-import com.alibaba.druid.sql.ast.SQLName;
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
+import com.alibaba.druid.sql.dialect.mysql.ast.MySqlObjectImpl;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;
public class MySqlLockTableStatement extends MySqlStatementImpl {
- private SQLExprTableSource tableSource;
-
- private LockType lockType;
-
- private List hints;
-
- public SQLExprTableSource getTableSource() {
- return tableSource;
- }
-
- public void setTableSource(SQLExprTableSource tableSource) {
- if (tableSource != null) {
- tableSource.setParent(this);
- }
- this.tableSource = tableSource;
- }
-
- public void setTableSource(SQLName name) {
- setTableSource(new SQLExprTableSource(name));
- }
-
- public LockType getLockType() {
- return lockType;
- }
-
- public void setLockType(LockType lockType) {
- this.lockType = lockType;
- }
+ private List- items = new ArrayList
- ();
+ @Override
public void accept0(MySqlASTVisitor visitor) {
if (visitor.visit(this)) {
- acceptChild(visitor, tableSource);
+ acceptChild(visitor, items);
}
visitor.endVisit(this);
}
@@ -70,11 +45,69 @@ public class MySqlLockTableStatement extends MySqlStatementImpl {
}
}
- public List getHints() {
- return hints;
+ public List
- getItems() {
+ return items;
}
- public void setHints(List hints) {
- this.hints = hints;
+ public void setItems(List
- items) {
+ this.items = items;
+ }
+
+ public LockType getLockType() {
+ if (items.size() == 1) {
+ return items.get(0).lockType;
+ }
+ return null;
+ }
+
+ public SQLExprTableSource getTableSource() {
+ if (items.size() == 1) {
+ return items.get(0).tableSource;
+ }
+ return null;
+ }
+
+ public static class Item extends MySqlObjectImpl {
+
+ private SQLExprTableSource tableSource = new SQLExprTableSource();
+
+ private LockType lockType;
+
+ private List hints;
+
+ @Override
+ public void accept0(MySqlASTVisitor visitor) {
+ if (visitor.visit(this)) {
+ acceptChild(visitor, tableSource);
+ }
+ visitor.endVisit(this);
+ }
+
+ public SQLExprTableSource getTableSource() {
+ return tableSource;
+ }
+
+ public void setTableSource(SQLExprTableSource tableSource) {
+ if (tableSource != null) {
+ tableSource.setParent(this);
+ }
+ this.tableSource = tableSource;
+ }
+
+ public LockType getLockType() {
+ return lockType;
+ }
+
+ public void setLockType(LockType lockType) {
+ this.lockType = lockType;
+ }
+
+ public List getHints() {
+ return hints;
+ }
+
+ public void setHints(List hints) {
+ this.hints = hints;
+ }
}
}
diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlCreateTableParser.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlCreateTableParser.java
index 03dbc80cf8..00d19ac00d 100644
--- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlCreateTableParser.java
+++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlCreateTableParser.java
@@ -106,7 +106,7 @@ public class MySqlCreateTableParser extends SQLCreateTableParser {
stmt.setSelect(query);
} else {
for (;;) {
- if (lexer.identifierEquals(FnvHash.Constants.FULLTEXT)) {
+ if (lexer.token() == Token.FULLTEXT) {
Lexer.SavePoint mark = lexer.mark();
lexer.nextToken();
if (lexer.token() == Token.KEY) {
@@ -119,8 +119,51 @@ public class MySqlCreateTableParser extends SQLCreateTableParser {
lexer.nextToken();
continue;
}
+ } else if (lexer.token() == Token.INDEX) {
+ lexer.nextToken();
+ MySqlTableIndex idx = new MySqlTableIndex();
+ idx.setIndexType("FULLTEXT");
+ idx.setName(this.exprParser.name());
+
+ accept(Token.LPAREN);
+ for (; ; ) {
+ idx.addColumn(this.exprParser.parseSelectOrderByItem());
+ if (!(lexer.token() == (Token.COMMA))) {
+ break;
+ } else {
+ lexer.nextToken();
+ }
+ }
+ stmt.getTableElementList().add(idx);
+ accept(Token.RPAREN);
+ if (lexer.token() == Token.RPAREN) {
+ break;
+ } else if (lexer.token() == Token.COMMA) {
+ lexer.nextToken();
+ continue;
+ }
} else {
- lexer.reset(mark);
+ MySqlTableIndex idx = new MySqlTableIndex();
+ idx.setIndexType("FULLTEXT");
+ idx.setName(this.exprParser.name());
+
+ accept(Token.LPAREN);
+ for (; ; ) {
+ idx.addColumn(this.exprParser.parseSelectOrderByItem());
+ if (!(lexer.token() == (Token.COMMA))) {
+ break;
+ } else {
+ lexer.nextToken();
+ }
+ }
+ stmt.getTableElementList().add(idx);
+ accept(Token.RPAREN);
+ if (lexer.token() == Token.RPAREN) {
+ break;
+ } else if (lexer.token() == Token.COMMA) {
+ lexer.nextToken();
+ continue;
+ }
}
} else if (lexer.identifierEquals(FnvHash.Constants.SPATIAL)) {
Lexer.SavePoint mark = lexer.mark();
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 1f61cb122a..c559b25cd2 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
@@ -64,6 +64,7 @@ public class MySqlLexer extends Lexer {
map.put("MOD", Token.MOD);
map.put("CONTAINS", Token.CONTAINS);
map.put("RLIKE", Token.RLIKE);
+ map.put("FULLTEXT", Token.FULLTEXT);
DEFAULT_MYSQL_KEYWORDS = new Keywords(map);
}
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 0b6b0663fb..50afefc6b2 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
@@ -65,7 +65,6 @@ public class MySqlStatementParser extends SQLStatementParser {
private static final String TABLES = "TABLES";
private static final String TEMPORARY = "TEMPORARY";
private static final String SPATIAL = "SPATIAL";
- private static final String FULLTEXT = "FULLTEXT";
private static final String LOW_PRIORITY = "LOW_PRIORITY";
private static final String CONNECTION = "CONNECTION";
private static final String EXTENDED = "EXTENDED";
@@ -258,7 +257,7 @@ public class MySqlStatementParser extends SQLStatementParser {
return parseCreateDatabase();
}
- if (lexer.token() == Token.UNIQUE || lexer.token() == Token.INDEX || lexer.identifierEquals(FULLTEXT)
+ if (lexer.token() == Token.UNIQUE || lexer.token() == Token.INDEX || lexer.token() == Token.FULLTEXT
|| lexer.identifierEquals(SPATIAL)) {
if (replace) {
lexer.reset(markBp, markChar, Token.CREATE);
@@ -505,8 +504,8 @@ public class MySqlStatementParser extends SQLStatementParser {
if (lexer.token() == Token.UNIQUE) {
stmt.setType("UNIQUE");
lexer.nextToken();
- } else if (lexer.identifierEquals(FULLTEXT)) {
- stmt.setType(FULLTEXT);
+ } else if (lexer.token() == Token.FULLTEXT) {
+ stmt.setType("FULLTEXT");
lexer.nextToken();
} else if (lexer.identifierEquals(SPATIAL)) {
stmt.setType(SPATIAL);
@@ -807,31 +806,62 @@ public class MySqlStatementParser extends SQLStatementParser {
}
MySqlLockTableStatement stmt = new MySqlLockTableStatement();
- stmt.setTableSource(this.exprParser.name());
- if (lexer.identifierEquals(READ)) {
- lexer.nextToken();
- if (lexer.identifierEquals(LOCAL)) {
+ for(;;) {
+ MySqlLockTableStatement.Item item = new MySqlLockTableStatement.Item();
+
+ SQLExprTableSource tableSource = null;
+ SQLName tableName = this.exprParser.name();
+
+
+ if (lexer.token() == Token.AS) {
+ lexer.nextToken();
+ String as = lexer.stringVal();
+ tableSource = new SQLExprTableSource(tableName, as);
lexer.nextToken();
- stmt.setLockType(LockType.READ_LOCAL);
} else {
- stmt.setLockType(LockType.READ);
+ tableSource = new SQLExprTableSource(tableName);
}
- } else if (lexer.identifierEquals(WRITE)) {
- lexer.nextToken();
- stmt.setLockType(LockType.WRITE);
- } else if (lexer.identifierEquals(FnvHash.Constants.LOW_PRIORITY)) {
- lexer.nextToken();
- acceptIdentifier(WRITE);
- lexer.nextToken();
- stmt.setLockType(LockType.LOW_PRIORITY_WRITE);
- } else {
- throw new ParserException("syntax error, expect READ or WRITE, actual " + lexer.token() + ", " + lexer.info());
+ item.setTableSource(tableSource);
+ stmt.getItems().add(item);
+
+ if (lexer.token() == Token.COMMA) {
+ lexer.nextToken();
+ continue;
+ }
+
+ if (lexer.identifierEquals(READ)) {
+ lexer.nextToken();
+ if (lexer.identifierEquals(LOCAL)) {
+ lexer.nextToken();
+ item.setLockType(LockType.READ_LOCAL);
+ } else {
+ item.setLockType(LockType.READ);
+ }
+ } else if (lexer.identifierEquals(WRITE)) {
+ lexer.nextToken();
+ item.setLockType(LockType.WRITE);
+ } else if (lexer.identifierEquals(FnvHash.Constants.LOW_PRIORITY)) {
+ lexer.nextToken();
+ acceptIdentifier(WRITE);
+ lexer.nextToken();
+ item.setLockType(LockType.LOW_PRIORITY_WRITE);
+ } else {
+ throw new ParserException(
+ "syntax error, expect READ or WRITE OR AS, actual " + lexer.token() + ", " + lexer.info());
+ }
+
+ if (lexer.token() == Token.HINT) {
+ item.setHints(this.exprParser.parseHints());
+ }
+
+ if (lexer.token() == Token.COMMA) {
+ lexer.nextToken();
+ continue;
+ }
+ break;
}
- if (lexer.token() == Token.HINT) {
- stmt.setHints(this.exprParser.parseHints());
- }
statementList.add(stmt);
return true;
}
@@ -860,25 +890,56 @@ public class MySqlStatementParser extends SQLStatementParser {
List hints = this.exprParser.parseHints();
boolean tddlHints = false;
+ boolean accept = false;
- final Token token = lexer.token();
+
+ boolean acceptHint = false;
+ switch (lexer.token()) {
+ case SELECT:
+ case WITH:
+ case DELETE:
+ case UPDATE:
+ case INSERT:
+ case SHOW:
+ case REPLACE:
+ case TRUNCATE:
+ case DROP:
+ case ALTER:
+ case CREATE:
+ case CHECK:
+ case SET:
+ acceptHint = true;
+ break;
+ case IDENTIFIER:
+ acceptHint = lexer.hash_lower() == FnvHash.Constants.DUMP
+ || lexer.hash_lower() == FnvHash.Constants.RENAME;
+ break;
+ default:
+ break;
+ }
if (hints.size() == 1
&& statementList.size() == 0
- && (token == Token.SELECT || token == Token.DELETE)) {
+ && acceptHint) {
SQLCommentHint hint = hints.get(0);
- String hintText = hint.getText();
- if (hintText.startsWith("+TDDL")) {
+ String hintText = hint.getText().toUpperCase();
+ if (hintText.startsWith("+TDDL")
+ || hintText.startsWith("+ TDDL")
+ || hintText.startsWith("TDDL")
+ || hintText.startsWith("!TDDL"))
+ {
tddlHints = true;
+ } else if(hintText.startsWith("+")) {
+ accept = true;
}
}
if (tddlHints) {
- SQLStatementImpl stmt;
- if (token == Token.SELECT) {
- stmt = (SQLSelectStatement) this.parseStatement();
- } else {
- stmt = (SQLDeleteStatement) this.parseStatement();
- }
+ SQLStatementImpl stmt = (SQLStatementImpl)this.parseStatement();
+ stmt.setHeadHints(hints);
+ statementList.add(stmt);
+ return true;
+ } else if (accept) {
+ SQLStatementImpl stmt = (SQLStatementImpl) this.parseStatement();
stmt.setHeadHints(hints);
statementList.add(stmt);
return true;
@@ -3463,7 +3524,7 @@ public class MySqlStatementParser extends SQLStatementParser {
lexer.nextToken();
parseAlterTableAddColumn(stmt);
} else if (lexer.token() == Token.INDEX
- || lexer.identifierEquals(FnvHash.Constants.FULLTEXT)
+ || lexer.token() == Token.FULLTEXT
|| lexer.identifierEquals(FnvHash.Constants.SPATIAL)) {
SQLAlterTableAddIndex item = parseAlterTableAddIndex();
item.setParent(stmt);
diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitor.java
index 340ff1b87c..3d83cc29df 100644
--- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitor.java
+++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitor.java
@@ -340,6 +340,10 @@ public interface MySqlASTVisitor extends SQLASTVisitor {
void endVisit(MySqlLockTableStatement x);
+ boolean visit(MySqlLockTableStatement.Item x);
+
+ void endVisit(MySqlLockTableStatement.Item x);
+
boolean visit(MySqlUnlockTablesStatement x);
void endVisit(MySqlUnlockTablesStatement x);
diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitorAdapter.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitorAdapter.java
index 34ae78d4d4..8cfb832c80 100644
--- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitorAdapter.java
+++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitorAdapter.java
@@ -788,6 +788,16 @@ public class MySqlASTVisitorAdapter extends SQLASTVisitorAdapter implements MySq
}
+ @Override
+ public boolean visit(MySqlLockTableStatement.Item x) {
+ return true;
+ }
+
+ @Override
+ public void endVisit(MySqlLockTableStatement.Item x) {
+
+ }
+
@Override
public boolean visit(MySqlUnlockTablesStatement x) {
return true;
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 0a62045fba..718daac486 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
@@ -2596,7 +2596,22 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
@Override
public boolean visit(MySqlLockTableStatement x) {
- print0(ucase ? "LOCK TABLES " : "lock tables ");
+ print0(ucase ? "LOCK TABLES" : "lock tables");
+ List items = x.getItems();
+ if(items.size() > 0) {
+ print(' ');
+ printAndAccept(items, ", ");
+ }
+ return false;
+ }
+
+ @Override
+ public void endVisit(MySqlLockTableStatement x) {
+
+ }
+
+ @Override
+ public boolean visit(MySqlLockTableStatement.Item x) {
x.getTableSource().accept(this);
if (x.getLockType() != null) {
print(' ');
@@ -2611,7 +2626,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
}
@Override
- public void endVisit(MySqlLockTableStatement x) {
+ public void endVisit(MySqlLockTableStatement.Item x) {
}
diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlSchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlSchemaStatVisitor.java
index 4d5bfb4ffd..00c58814d1 100644
--- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlSchemaStatVisitor.java
+++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlSchemaStatVisitor.java
@@ -886,6 +886,16 @@ public class MySqlSchemaStatVisitor extends SchemaStatVisitor implements MySqlAS
}
+ @Override
+ public boolean visit(MySqlLockTableStatement.Item x) {
+ return false;
+ }
+
+ @Override
+ public void endVisit(MySqlLockTableStatement.Item x) {
+
+ }
+
@Override
public boolean visit(MySqlUnlockTablesStatement x) {
return false;
diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGExprParser.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGExprParser.java
index 406bb9596d..1a3465cf45 100644
--- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGExprParser.java
+++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGExprParser.java
@@ -334,4 +334,15 @@ public class PGExprParser extends SQLExprParser {
}
return alias;
}
+
+ protected void filter(SQLAggregateExpr x) {
+ if (lexer.identifierEquals(FnvHash.Constants.FILTER)) {
+ lexer.nextToken();
+ accept(Token.LPAREN);
+ accept(Token.WHERE);
+ SQLExpr filter = this.expr();
+ accept(Token.RPAREN);
+ x.setFilter(filter);
+ }
+ }
}
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 443a95316f..4aba23d22a 100644
--- a/src/main/java/com/alibaba/druid/sql/parser/Lexer.java
+++ b/src/main/java/com/alibaba/druid/sql/parser/Lexer.java
@@ -474,6 +474,7 @@ public class Lexer {
}
if (c1 == '\'') {
+ bufPos = 0;
++pos;
ch = '\'';
scanString();
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 942816d35b..0aef79a1b4 100644
--- a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java
+++ b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java
@@ -1445,14 +1445,21 @@ public class SQLExprParser extends SQLParser {
accept(Token.RPAREN);
+ if (lexer.identifierEquals(FnvHash.Constants.FILTER)) {
+ filter(aggregateExpr);
+ }
+
if (lexer.token == Token.OVER) {
over(aggregateExpr);
-
}
return aggregateExpr;
}
+ protected void filter(SQLAggregateExpr aggregateExpr) {
+
+ }
+
protected void over(SQLAggregateExpr aggregateExpr) {
lexer.nextToken();
@@ -2263,6 +2270,8 @@ public class SQLExprParser extends SQLParser {
}
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Equality, rightExp, dbType);
+ } else {
+ return expr;
}
break;
case TILDE:
@@ -2274,6 +2283,8 @@ public class SQLExprParser extends SQLParser {
rightExp = relationalRest(rightExp);
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.POSIX_Regular_Match, rightExp, getDbType());
+ } else {
+ return expr;
}
break;
case TILDE_STAR:
@@ -2281,6 +2292,8 @@ public class SQLExprParser extends SQLParser {
lexer.nextToken();
rightExp = relational();
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.POSIX_Regular_Match_Insensitive, rightExp, getDbType());
+ } else {
+ return expr;
}
break;
case BANG_TILDE:
@@ -2288,6 +2301,8 @@ public class SQLExprParser extends SQLParser {
lexer.nextToken();
rightExp = relational();
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.POSIX_Regular_Not_Match, rightExp, getDbType());
+ } else {
+ return expr;
}
break;
case BANG_TILDE_STAR:
@@ -2295,6 +2310,8 @@ public class SQLExprParser extends SQLParser {
lexer.nextToken();
rightExp = relational();
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.POSIX_Regular_Not_Match_POSIX_Regular_Match_Insensitive, rightExp, getDbType());
+ } else {
+ return expr;
}
break;
case TILDE_EQ:
@@ -2302,6 +2319,8 @@ public class SQLExprParser extends SQLParser {
lexer.nextToken();
rightExp = relational();
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.SAME_AS, rightExp, getDbType());
+ } else {
+ return expr;
}
break;
case RLIKE:
@@ -2331,6 +2350,8 @@ public class SQLExprParser extends SQLParser {
rightExp = relational();
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.SIMILAR_TO, rightExp, getDbType());
+ } else {
+ return expr;
}
break;
default:
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 0174f36a6c..1466043612 100644
--- a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java
+++ b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java
@@ -370,6 +370,13 @@ public class SQLStatementParser extends SQLParser {
continue;
}
+ if (lexer.identifierEquals("DUMP")) {
+ SQLStatement stmt = parseDump();
+ statementList.add(stmt);
+
+ continue;
+ }
+
if (lexer.identifierEquals(FnvHash.Constants.COMMIT)) {
SQLStatement stmt = parseCommit();
@@ -427,6 +434,26 @@ public class SQLStatementParser extends SQLParser {
}
}
+ public SQLStatement parseDump() {
+ SQLDumpStatement stmt = new SQLDumpStatement();
+ acceptIdentifier("DUMP");
+ acceptIdentifier("DATA");
+
+ if (lexer.identifierEquals(FnvHash.Constants.OVERWRITE)) {
+ lexer.nextToken();
+ stmt.setOverwrite(true);
+ }
+
+ if (lexer.token == Token.INTO) {
+ lexer.nextToken();
+ stmt.setInto(this.exprParser.expr());
+ }
+
+ SQLSelect select = createSQLSelectParser().select();
+ stmt.setSelect(select);
+ return stmt;
+ }
+
public SQLStatement parseDrop() {
List beforeComments = null;
@@ -2777,7 +2804,7 @@ public class SQLStatementParser extends SQLParser {
protected SQLAlterTableAddIndex parseAlterTableAddIndex() {
SQLAlterTableAddIndex item = new SQLAlterTableAddIndex();
- if (lexer.identifierEquals(FnvHash.Constants.FULLTEXT)) {
+ if (lexer.token == Token.FULLTEXT) {
lexer.nextToken();
item.setType("FULLTEXT");
} else if (lexer.identifierEquals(FnvHash.Constants.SPATIAL)) {
diff --git a/src/main/java/com/alibaba/druid/sql/parser/Token.java b/src/main/java/com/alibaba/druid/sql/parser/Token.java
index fd9f07cdd8..a3a28bee92 100644
--- a/src/main/java/com/alibaba/druid/sql/parser/Token.java
+++ b/src/main/java/com/alibaba/druid/sql/parser/Token.java
@@ -102,6 +102,7 @@ public enum Token {
IN("IN"),
CONTAINS("CONTAINS"),
RLIKE("RLIKE"),
+ FULLTEXT("FULLTEXT"),
NEW("NEW"),
ASC("ASC"),
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 4eef77f071..ee145b1d0e 100644
--- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java
+++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java
@@ -1562,6 +1562,13 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
over.accept(this);
}
+ final SQLExpr filter = x.getFilter();
+ if (filter != null) {
+ print0(ucase ? "FILTER (WHERE " : "filter (where ");
+ printExpr(filter);
+ print(')');
+ }
+
this.parameterized = parameterized;
return false;
}
@@ -6579,6 +6586,32 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet
return false;
}
+ @Override
+ public boolean visit(SQLDumpStatement x) {
+ List headHints = x.getHeadHintsDirect();
+ if (headHints != null) {
+ for (SQLCommentHint hint : headHints) {
+ hint.accept(this);
+ println();
+ }
+ }
+
+ print0(ucase ? "DUMP DATA " : "dump data ");
+
+
+ if (x.isOverwrite()) {
+ print0(ucase ? "OVERWRITE " : "overwrite ");
+ }
+
+ SQLExprTableSource into = x.getInto();
+ if (into != null) {
+ into.accept(this);
+ }
+
+ x.getSelect().accept(this);
+ return false;
+ }
+
public void print(float value) {
if (this.appender == null) {
return;
diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java
index 17285df6bb..3e72e44c92 100644
--- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java
+++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java
@@ -842,4 +842,7 @@ public interface SQLASTVisitor {
boolean visit(SQLWindow x);
void endVisit(SQLWindow x);
+ boolean visit(SQLDumpStatement x);
+ void endVisit(SQLDumpStatement x);
+
}
diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java
index 1900a2dfa7..459f863299 100644
--- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java
+++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java
@@ -1990,7 +1990,6 @@ public class SQLASTVisitorAdapter implements SQLASTVisitor {
}
-
@Override
public boolean visit(SQLWindow x) {
return true;
@@ -2000,6 +1999,14 @@ public class SQLASTVisitorAdapter implements SQLASTVisitor {
}
+ @Override
+ public boolean visit(SQLDumpStatement x) {
+ return true;
+ }
+
+ public void endVisit(SQLDumpStatement x) {
+
+ }
public final boolean isEnabled(VisitorFeature feature) {
return VisitorFeature.isEnabled(this.features, feature);
diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java
index d7c989ac66..e1de81e413 100644
--- a/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java
+++ b/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java
@@ -2515,4 +2515,23 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter {
}
return false;
}
+
+ public boolean visit(SQLDumpStatement x) {
+ if (repository != null
+ && x.getParent() == null) {
+ repository.resolve(x);
+ }
+
+ final SQLExprTableSource into = x.getInto();
+ if (into != null) {
+ into.accept(this);
+ }
+
+ final SQLSelect select = x.getSelect();
+ if (select != null) {
+ select.accept(this);
+ }
+
+ return false;
+ }
}
diff --git a/src/main/java/com/alibaba/druid/util/FnvHash.java b/src/main/java/com/alibaba/druid/util/FnvHash.java
index 0a65b9e82d..1177354e88 100644
--- a/src/main/java/com/alibaba/druid/util/FnvHash.java
+++ b/src/main/java/com/alibaba/druid/util/FnvHash.java
@@ -582,6 +582,7 @@ public final class FnvHash {
long SCHEDULE = fnv1a_64_lower("SCHEDULE");
long COMPLETION = fnv1a_64_lower("COMPLETION");
long RENAME = fnv1a_64_lower("RENAME");
+ long DUMP = fnv1a_64_lower("DUMP");
long AT = fnv1a_64_lower("AT");
long LANGUAGE = fnv1a_64_lower("LANGUAGE");
long LOGFILE = fnv1a_64_lower("LOGFILE");
@@ -649,5 +650,8 @@ public final class FnvHash {
long GENERATED = fnv1a_64_lower("GENERATED");
long ALWAYS = fnv1a_64_lower("ALWAYS");
long INCREMENT = fnv1a_64_lower("INCREMENT");
+
+ long OVERWRITE = fnv1a_64_lower("OVERWRITE");
+ long FILTER = fnv1a_64_lower("FILTER");
}
}
diff --git a/src/main/resources/support/http/resources/js/lang.js b/src/main/resources/support/http/resources/js/lang.js
index 5953ad54af..8dedabf525 100644
--- a/src/main/resources/support/http/resources/js/lang.js
+++ b/src/main/resources/support/http/resources/js/lang.js
@@ -10,7 +10,7 @@ druid.lang = function() {
'WebApp' : ['WebApp' , 'Web应用'],
'WebURI' : ['WebURI' , 'URI监控'],
'Web Session' : ['Web Session' , 'Session监控'],
- 'Spring' : ['Spring' , 'spring监控'],
+ 'Spring' : ['Spring' , 'Spring监控'],
'JSON API' : ['JSON API' , 'JSON API'],
'ResetAll' : ['Reset All' , '重置'],
'LogAndReset' : ['Log And Reset' , '记录日志并重置'],
@@ -21,8 +21,8 @@ druid.lang = function() {
'Drivers' : ['Drivers' , '驱动'],
'ResetEnable' : ['ResetEnable' , '是否允许重置'],
'ResetCount' : ['ResetCount' , '重置次数'],
- 'JavaVersion' : ['JavaVersion' , 'java版本'],
- 'JavaVMName' : ['JavaVMName' , 'jvm名称'],
+ 'JavaVersion' : ['JavaVersion' , 'Java版本'],
+ 'JavaVMName' : ['JavaVMName' , 'JVM名称'],
'JavaClassPath' : ['JavaClassPath' , 'classpath路径'],
'StartTime' : ['StartTime' , '启动时间'],
@@ -79,9 +79,9 @@ druid.lang = function() {
'SQLList' : ['SQL List', 'sql列表'],
'UserNameDesc' : ['Specify the username used when creating a new connection.', '指定建立连接时使用的用户名'],
- 'URLDesc' : ['The JDBC driver connection URL', 'jdbc连接字符串'],
+ 'URLDesc' : ['The JDBC driver connection URL', 'JDBC连接字符串'],
'DbTypeDesc' : ['database type', '数据库类型'],
- 'DriverClassNameDesc' : ['The fully qualifed name of the JDBC driver class', 'jdbc驱动的类名'],
+ 'DriverClassNameDesc' : ['The fully qualifed name of the JDBC driver class', 'JDBC驱动的类名'],
'FilterClassNamesDesc' : ['All the fully qualifed name of the filter classes', 'filter的类名'],
'TestOnBorrowDesc' : [' Test or not when borrow a connection', '是否在获得连接后检测其可用性'],
'TestWhileIdleDesc' : ['Test or not when a connection is idle for a while', '是否在连接空闲一段时间后检测其可用性'],
@@ -232,8 +232,8 @@ druid.lang = function() {
'WallStat':['Wall Stat', '防御统计'],
'TableStat':['Table Stat', '表访问统计'],
'FunctionStat':['Function Stat', '函数调用统计'],
- 'SQLStatWhiteList':['SQL Stat - White List', 'SQL防御统计 - 白名单'],
- 'SQLStatBlackList':['SQL Stat - Black List', 'SQL防御统计 - 黑名单'],
+ 'SQLStatWhiteList':['SQL Stat - White List', 'SQL防御统计 - 白名单'],
+ 'SQLStatBlackList':['SQL Stat - Black List', 'SQL防御统计 - 黑名单'],
/**session-detail*/
'PrincipalOnly':['Principal Only', 'Principal过滤'],
'SESSIONID':['SESSIONID', 'SESSIONID'],
diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/AdsDumpTest_0.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/AdsDumpTest_0.java
new file mode 100644
index 0000000000..351ec5c4ba
--- /dev/null
+++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/AdsDumpTest_0.java
@@ -0,0 +1,32 @@
+package com.alibaba.druid.bvt.sql.mysql;
+
+import com.alibaba.druid.sql.SQLUtils;
+import com.alibaba.druid.sql.ast.SQLStatement;
+import com.alibaba.druid.sql.ast.statement.SQLDumpStatement;
+import com.alibaba.druid.util.JdbcConstants;
+import junit.framework.TestCase;
+
+import java.util.List;
+
+public class AdsDumpTest_0 extends TestCase {
+
+ public void test_0() throws Exception {
+ String sql = "/*+dump-merge=true*/DUMP DATA SELECT amp.buyer_add_cart_info.buyer_id,amp.buyer_add_cart_info.pre_score,amp.buyer_add_cart_info.cart_price FROM amp.buyer_add_cart_info JOIN amp.crm_user_base_info ON amp.crm_user_base_info.user_id = amp.buyer_add_cart_info.buyer_id where (((amp.buyer_add_cart_info.seller_id=1921906956)) AND ((amp.buyer_add_cart_info.auction_id=562769960283)) AND ((amp.buyer_add_cart_info.show_price>=13300))) LIMIT 144800 ";
+
+ List statementList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);
+ SQLDumpStatement stmt = (SQLDumpStatement)statementList.get(0);
+
+ assertEquals(1, statementList.size());
+
+ assertEquals("/*+dump-merge=true*/\n" +
+ "DUMP DATA SELECT amp.buyer_add_cart_info.buyer_id, amp.buyer_add_cart_info.pre_score, amp.buyer_add_cart_info.cart_price\n" +
+ "FROM amp.buyer_add_cart_info\n" +
+ "\tJOIN amp.crm_user_base_info ON amp.crm_user_base_info.user_id = amp.buyer_add_cart_info.buyer_id\n" +
+ "WHERE amp.buyer_add_cart_info.seller_id = 1921906956\n" +
+ "\tAND amp.buyer_add_cart_info.auction_id = 562769960283\n" +
+ "\tAND amp.buyer_add_cart_info.show_price >= 13300\n" +
+ "LIMIT 144800", stmt.toString());
+ }
+
+
+}
\ No newline at end of file
diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlDumpTest.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlDumpTest.java
new file mode 100644
index 0000000000..d151892209
--- /dev/null
+++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlDumpTest.java
@@ -0,0 +1,64 @@
+/*
+ * 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;
+
+import com.alibaba.druid.sql.MysqlTest;
+import com.alibaba.druid.sql.ast.SQLStatement;
+import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;
+import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;
+
+import java.util.List;
+
+public class MySqlDumpTest extends MysqlTest {
+
+ public void test_0() throws Exception {
+ String sql = "dump data into 'odps://ktv_market_analyzing/bohan_test_001/ds=20171233/seller_bucket=9727' " +
+ "select '6225607' as crowd_snapshot_id, a.seller_id as seller_id, a.buyer_id as buyer_id " +
+ "from amp.otpx_buyer_seller_relation_detail_to_garuda a " +
+ "join amp.otp_user_base_info b on b.user_id= a.buyer_id " +
+ "where(((a.seller_id= 765844183 and a.seller_zone= 765844183%20+ 1000)) and((a.last_pay_date>= 20151226 and a.last_pay_date<= 20171215)) and((a.is_market_target in('3'))))";
+
+ MySqlStatementParser parser = new MySqlStatementParser(sql);
+ List statementList = parser.parseStatementList();
+ SQLStatement stmt = statementList.get(0);
+// print(statementList);
+
+ assertEquals(1, statementList.size());
+
+ MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();
+ 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(2, visitor.getTables().size());
+ assertEquals(6, visitor.getColumns().size());
+ assertEquals(7, visitor.getConditions().size());
+
+ assertTrue(visitor.containsTable("amp.otp_user_base_info"));
+ assertTrue(visitor.containsTable("amp.otpx_buyer_seller_relation_detail_to_garuda"));
+// assertTrue(visitor.getTables().containsKey(new TableStat.Name("t2")));
+
+ assertTrue(visitor.containsColumn("amp.otp_user_base_info", "user_id"));
+ assertTrue(visitor.containsColumn("amp.otpx_buyer_seller_relation_detail_to_garuda", "buyer_id"));
+ assertTrue(visitor.containsColumn("amp.otpx_buyer_seller_relation_detail_to_garuda", "seller_id"));
+ assertTrue(visitor.containsColumn("amp.otpx_buyer_seller_relation_detail_to_garuda", "seller_zone"));
+ assertTrue(visitor.containsColumn("amp.otpx_buyer_seller_relation_detail_to_garuda", "is_market_target"));
+ assertTrue(visitor.containsColumn("amp.otpx_buyer_seller_relation_detail_to_garuda", "last_pay_date"));
+ }
+}
diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlDumpTest_1.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlDumpTest_1.java
new file mode 100644
index 0000000000..d87546884a
--- /dev/null
+++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlDumpTest_1.java
@@ -0,0 +1,59 @@
+/*
+ * 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;
+
+import com.alibaba.druid.sql.MysqlTest;
+import com.alibaba.druid.sql.ast.SQLStatement;
+import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;
+import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;
+
+import java.util.List;
+
+public class MySqlDumpTest_1 extends MysqlTest {
+
+ public void test_0() throws Exception {
+ String sql = "DUMP DATA OVERWRITE INTO 'odps://cod_garuda/wenyu_meta_person' select cid, cname, dept, gender, pid from wenyu_meta_person limit 10;";
+
+ MySqlStatementParser parser = new MySqlStatementParser(sql);
+ List statementList = parser.parseStatementList();
+ SQLStatement stmt = statementList.get(0);
+// print(statementList);
+
+ assertEquals(1, statementList.size());
+
+ MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();
+ 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(5, visitor.getColumns().size());
+ assertEquals(0, visitor.getConditions().size());
+
+ assertTrue(visitor.containsTable("wenyu_meta_person"));
+// assertTrue(visitor.getTables().containsKey(new TableStat.Name("t2")));
+
+ assertTrue(visitor.containsColumn("wenyu_meta_person", "cid"));
+ assertTrue(visitor.containsColumn("wenyu_meta_person", "cname"));
+ assertTrue(visitor.containsColumn("wenyu_meta_person", "dept"));
+ assertTrue(visitor.containsColumn("wenyu_meta_person", "gender"));
+ assertTrue(visitor.containsColumn("wenyu_meta_person", "pid"));
+
+ }
+}
diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest112.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest112.java
new file mode 100644
index 0000000000..b8141e7b6a
--- /dev/null
+++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest112.java
@@ -0,0 +1,50 @@
+package com.alibaba.druid.bvt.sql.mysql.createTable;
+
+import com.alibaba.druid.sql.MysqlTest;
+import com.alibaba.druid.sql.SQLUtils;
+import com.alibaba.druid.sql.ast.SQLStatement;
+import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;
+import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;
+import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;
+import com.alibaba.druid.sql.visitor.SchemaStatVisitor;
+import com.alibaba.druid.util.JdbcConstants;
+
+import java.util.List;
+
+public class MySqlCreateTableTest112 extends MysqlTest {
+
+ public void test_0() throws Exception {
+ String sql = "CREATE TABLE opening_lines ( " +
+ "id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY" +
+ ", opening_line TEXT(500)" +
+ ", author VARCHAR(200)" +
+ ", title VARCHAR(200)" +
+ ", FULLTEXT idx (opening_line) " +
+ ") ENGINE=InnoDB;";
+
+ MySqlStatementParser parser = new MySqlStatementParser(sql);
+ List statementList = parser.parseStatementList();
+ MySqlCreateTableStatement stmt = (MySqlCreateTableStatement)statementList.get(0);
+
+ assertEquals(1, statementList.size());
+ assertEquals(5, stmt.getTableElementList().size());
+
+ assertEquals("CREATE TABLE opening_lines (\n" +
+ "\tid INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,\n" +
+ "\topening_line TEXT(500),\n" +
+ "\tauthor VARCHAR(200),\n" +
+ "\ttitle VARCHAR(200),\n" +
+ "\tFULLTEXT INDEX idx(opening_line)\n" +
+ ") ENGINE = InnoDB;", stmt.toString());
+
+ SchemaStatVisitor v = SQLUtils.createSchemaStatVisitor(JdbcConstants.MYSQL);
+ stmt.accept(v);
+
+ assertEquals(4, v.getColumns().size());
+ SQLColumnDefinition column = stmt.findColumn("id");
+ assertNotNull(column);
+ assertEquals(2, column.getConstraints().size());
+ assertTrue(column.isPrimaryKey());
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/select/MySqlSelectTest_188.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/select/MySqlSelectTest_188.java
new file mode 100644
index 0000000000..43f465dedb
--- /dev/null
+++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/select/MySqlSelectTest_188.java
@@ -0,0 +1,151 @@
+package com.alibaba.druid.bvt.sql.mysql.select;
+
+import com.alibaba.druid.sql.MysqlTest;
+import com.alibaba.druid.sql.ast.SQLStatement;
+import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
+import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;
+
+import java.util.List;
+
+public class MySqlSelectTest_188 extends MysqlTest {
+
+ public void test_0() throws Exception {
+ String sql = "( ( SELECT user_id FROM (select user_id, havana_id, create_time, reg_days, own, reg_own_group, reg_src_group, reg_channel, src, global_city_name, locale, cid, cid_name, account_certify_type, certified_from, certified_time, certify_type, is_certified, account_type, address, age, sex, birthday, global_province_name, group_phone_area_no, group_phone_zone_no, l_level, crm_label, account_structure, account_frozen, hid_b2b, hid_taobao, is_aliyun_test_user, is_aliyun_user, is_enterprise, is_enterprise_account, is_global_user, is_net_test_user, is_oversea_user, is_valid_reg_user, is_net_user, parent_pk, taobao_account, update_time, user_region, fenxiao_create_time, fenxiao_label, fenxiao_parent_uid, fenxiao_region, crm_customer_priority, crm_customer_rank, order_cnt, cloud_order_cnt, cloud_market_order_cnt, count_ecs_paid_order, count_rds_paid_order, count_oss_paid_order, count_cdn_paid_order, count_slb_paid_order, count_nas_paid_order, count_mongodb_paid_order, count_eip_paid_order, count_redis_paid_order, count_communicate_paid_order, is_paid_retain, count_1_all_visit, count_7_all_visit, count_15_all_visit, count_30_all_visit, is_retain_d,count_1_yq_visit,count_7_yq_visit,count_15_yq_visit,count_30_yq_visit,count_1_promotion_visit,count_7_promotion_visit,count_15_promotion_visit,count_30_promotion_visit,count_1_market_visit,count_7_market_visit,count_15_market_visit,count_30_market_visit,count_1_search_visit,count_7_search_visit,count_15_search_visit,count_30_search_visit,count_1_help_visit,count_7_help_visit,count_15_help_visit,count_30_help_visit,count_7_domain_visit,count_15_domain_visit,count_30_domain_visit,count_1_beian_visit,count_7_beian_visit,count_15_beian_visit,count_30_beian_visit,count_1_wanwang_visit,count_7_wanwang_visit,count_15_wanwang_visit,count_30_wanwang_visit,count_1_domain_visit,crm_biz_category,cloud_pay_greater_zero_order_cnt, retain_cnt_d, retain_cnt_ecs_d, retain_cnt_rds_d, retain_cnt_oss_d, retain_cnt_cdn_d, retain_cnt_slb_d, retain_cnt_nas_d, retain_cnt_mangodb_d, retain_cnt_eip_d, retain_cnt_redis_d, retain_cnt_communication_d, retain_cnt_domain_d, retain_cnt_email_d, retain_cnt_dns_d from user_info_offline where user_id = 1953401122571952) WHERE create_time>'2018-01-01 00:00:00' EXCEPT SELECT user_id FROM (select user_id, create_time, reg_channel, src, certified_from, certified_time, account_certify_type, is_certified, crm_label, order_cnt, cloud_order_cnt, cloud_market_order_cnt, count_ecs_paid_order, count_rds_paid_order, count_oss_paid_order, count_cdn_paid_order, count_slb_paid_order, count_nas_paid_order, count_mongodb_paid_order, count_eip_paid_order, count_redis_paid_order, count_communicate_paid_order from user_info_online where user_id = 1953401122571952) ) UNION SELECT coalesce(a.user_id, b.user_id) as user_id FROM (select user_id, create_time, reg_channel, src, certified_from, certified_time, account_certify_type, is_certified, crm_label, order_cnt, cloud_order_cnt, cloud_market_order_cnt, count_ecs_paid_order, count_rds_paid_order, count_oss_paid_order, count_cdn_paid_order, count_slb_paid_order, count_nas_paid_order, count_mongodb_paid_order, count_eip_paid_order, count_redis_paid_order, count_communicate_paid_order from user_info_online where user_id = 1953401122571952) a LEFT JOIN (select user_id, havana_id, create_time, reg_days, own, reg_own_group, reg_src_group, reg_channel, src, global_city_name, locale, cid, cid_name, account_certify_type, certified_from, certified_time, certify_type, is_certified, account_type, address, age, sex, birthday, global_province_name, group_phone_area_no, group_phone_zone_no, l_level, crm_label,account_structure, account_frozen, hid_b2b, hid_taobao, is_aliyun_test_user, is_aliyun_user, is_enterprise, is_enterprise_account, is_global_user, is_net_test_user, is_oversea_user, is_valid_reg_user, is_net_user, parent_pk, taobao_account, update_time, user_region, fenxiao_create_time, fenxiao_label, fenxiao_parent_uid, fenxiao_region, crm_customer_priority, crm_customer_rank,order_cnt, cloud_order_cnt, cloud_market_order_cnt, count_ecs_paid_order, count_rds_paid_order, count_oss_paid_order, count_cdn_paid_order, count_slb_paid_order, count_nas_paid_order, count_mongodb_paid_order, count_eip_paid_order, count_redis_paid_order, count_communicate_paid_order, is_paid_retain, count_1_all_visit, count_7_all_visit, count_15_all_visit, count_30_all_visit, is_retain_d,count_1_yq_visit,count_7_yq_visit,count_15_yq_visit,count_30_yq_visit,count_1_promotion_visit,count_7_promotion_visit,count_15_promotion_visit,count_30_promotion_visit,count_1_market_visit,count_7_market_visit,count_15_market_visit,count_30_market_visit,count_1_search_visit,count_7_search_visit,count_15_search_visit,count_30_search_visit,count_1_help_visit,count_7_help_visit,count_15_help_visit,count_30_help_visit,count_7_domain_visit,count_15_domain_visit,count_30_domain_visit,count_1_beian_visit,count_7_beian_visit,count_15_beian_visit,count_30_beian_visit,count_1_wanwang_visit,count_7_wanwang_visit,count_15_wanwang_visit,count_30_wanwang_visit,count_1_domain_visit,crm_biz_category,cloud_pay_greater_zero_order_cnt, retain_cnt_d, retain_cnt_ecs_d, retain_cnt_rds_d, retain_cnt_oss_d, retain_cnt_cdn_d, retain_cnt_slb_d, retain_cnt_nas_d, retain_cnt_mangodb_d, retain_cnt_eip_d, retain_cnt_redis_d, retain_cnt_communication_d, retain_cnt_domain_d, retain_cnt_email_d, retain_cnt_dns_d from user_info_offline where user_id = 1953401122571952) b ON a.user_id = b.user_id WHERE ( (a.create_time>'2018-01-01 00:00:00') or (a.create_time is null and b.create_time>'2018-01-01 00:00:00') ) ) INTERSECT ( SELECT coalesce(a.user_id, b.user_id) as user_id FROM (select user_id, create_time, reg_channel, src, certified_from, certified_time, account_certify_type, is_certified, crm_label, order_cnt, cloud_order_cnt, cloud_market_order_cnt, count_ecs_paid_order, count_rds_paid_order, count_oss_paid_order, count_cdn_paid_order, count_slb_paid_order, count_nas_paid_order, count_mongodb_paid_order, count_eip_paid_order, count_redis_paid_order, count_communicate_paid_order from user_info_online where user_id = 1953401122571952) a FULL JOIN (select user_id, havana_id, create_time, reg_days, own, reg_own_group, reg_src_group, reg_channel, src, global_city_name, locale, cid, cid_name, account_certify_type, certified_from, certified_time, certify_type, is_certified, account_type, address, age, sex, birthday, global_province_name, group_phone_area_no, group_phone_zone_no, l_level, crm_label,account_structure, account_frozen, hid_b2b, hid_taobao, is_aliyun_test_user, is_aliyun_user, is_enterprise, is_enterprise_account, is_global_user, is_net_test_user, is_oversea_user, is_valid_reg_user, is_net_user, parent_pk, taobao_account, update_time, user_region, fenxiao_create_time, fenxiao_label, fenxiao_parent_uid, fenxiao_region, crm_customer_priority, crm_customer_rank,order_cnt, cloud_order_cnt, cloud_market_order_cnt, count_ecs_paid_order, count_rds_paid_order, count_oss_paid_order, count_cdn_paid_order, count_slb_paid_order, count_nas_paid_order, count_mongodb_paid_order, count_eip_paid_order, count_redis_paid_order, count_communicate_paid_order, is_paid_retain, count_1_all_visit, count_7_all_visit, count_15_all_visit, count_30_all_visit, is_retain_d,count_1_yq_visit,count_7_yq_visit,count_15_yq_visit,count_30_yq_visit,count_1_promotion_visit,count_7_promotion_visit,count_15_promotion_visit,count_30_promotion_visit,count_1_market_visit,count_7_market_visit,count_15_market_visit,count_30_market_visit,count_1_search_visit,count_7_search_visit,count_15_search_visit,count_30_search_visit,count_1_help_visit,count_7_help_visit,count_15_help_visit,count_30_help_visit,count_7_domain_visit,count_15_domain_visit,count_30_domain_visit,count_1_beian_visit,count_7_beian_visit,count_15_beian_visit,count_30_beian_visit,count_1_wanwang_visit,count_7_wanwang_visit,count_15_wanwang_visit,count_30_wanwang_visit,count_1_domain_visit,crm_biz_category,cloud_pay_greater_zero_order_cnt, retain_cnt_d, retain_cnt_ecs_d, retain_cnt_rds_d, retain_cnt_oss_d, retain_cnt_cdn_d, retain_cnt_slb_d, retain_cnt_nas_d, retain_cnt_mangodb_d, retain_cnt_eip_d, retain_cnt_redis_d, retain_cnt_communication_d, retain_cnt_domain_d, retain_cnt_email_d, retain_cnt_dns_d from user_info_offline where user_id = 1953401122571952) b ON a.user_id = b.user_id WHERE ( (a.account_certify_type='personal') or (a.account_certify_type is null and b.account_certify_type='personal') ) )";
+
+// System.out.println(sql);
+
+ MySqlStatementParser parser = new MySqlStatementParser(sql);
+ List statementList = parser.parseStatementList();
+ SQLSelectStatement stmt = (SQLSelectStatement)statementList.get(0);
+
+ assertEquals(1, statementList.size());
+
+ assertEquals("((SELECT user_id\n" +
+ "FROM (\n" +
+ "\tSELECT user_id, havana_id, create_time, reg_days, own\n" +
+ "\t\t, reg_own_group, reg_src_group, reg_channel, src, global_city_name\n" +
+ "\t\t, locale, cid, cid_name, account_certify_type, certified_from\n" +
+ "\t\t, certified_time, certify_type, is_certified, account_type, address\n" +
+ "\t\t, age, sex, birthday, global_province_name, group_phone_area_no\n" +
+ "\t\t, group_phone_zone_no, l_level, crm_label, account_structure, account_frozen\n" +
+ "\t\t, hid_b2b, hid_taobao, is_aliyun_test_user, is_aliyun_user, is_enterprise\n" +
+ "\t\t, is_enterprise_account, is_global_user, is_net_test_user, is_oversea_user, is_valid_reg_user\n" +
+ "\t\t, is_net_user, parent_pk, taobao_account, update_time, user_region\n" +
+ "\t\t, fenxiao_create_time, fenxiao_label, fenxiao_parent_uid, fenxiao_region, crm_customer_priority\n" +
+ "\t\t, crm_customer_rank, order_cnt, cloud_order_cnt, cloud_market_order_cnt, count_ecs_paid_order\n" +
+ "\t\t, count_rds_paid_order, count_oss_paid_order, count_cdn_paid_order, count_slb_paid_order, count_nas_paid_order\n" +
+ "\t\t, count_mongodb_paid_order, count_eip_paid_order, count_redis_paid_order, count_communicate_paid_order, is_paid_retain\n" +
+ "\t\t, count_1_all_visit, count_7_all_visit, count_15_all_visit, count_30_all_visit, is_retain_d\n" +
+ "\t\t, count_1_yq_visit, count_7_yq_visit, count_15_yq_visit, count_30_yq_visit, count_1_promotion_visit\n" +
+ "\t\t, count_7_promotion_visit, count_15_promotion_visit, count_30_promotion_visit, count_1_market_visit, count_7_market_visit\n" +
+ "\t\t, count_15_market_visit, count_30_market_visit, count_1_search_visit, count_7_search_visit, count_15_search_visit\n" +
+ "\t\t, count_30_search_visit, count_1_help_visit, count_7_help_visit, count_15_help_visit, count_30_help_visit\n" +
+ "\t\t, count_7_domain_visit, count_15_domain_visit, count_30_domain_visit, count_1_beian_visit, count_7_beian_visit\n" +
+ "\t\t, count_15_beian_visit, count_30_beian_visit, count_1_wanwang_visit, count_7_wanwang_visit, count_15_wanwang_visit\n" +
+ "\t\t, count_30_wanwang_visit, count_1_domain_visit, crm_biz_category, cloud_pay_greater_zero_order_cnt, retain_cnt_d\n" +
+ "\t\t, retain_cnt_ecs_d, retain_cnt_rds_d, retain_cnt_oss_d, retain_cnt_cdn_d, retain_cnt_slb_d\n" +
+ "\t\t, retain_cnt_nas_d, retain_cnt_mangodb_d, retain_cnt_eip_d, retain_cnt_redis_d, retain_cnt_communication_d\n" +
+ "\t\t, retain_cnt_domain_d, retain_cnt_email_d, retain_cnt_dns_d\n" +
+ "\tFROM user_info_offline\n" +
+ "\tWHERE user_id = 1953401122571952\n" +
+ ")\n" +
+ "WHERE create_time > '2018-01-01 00:00:00'\n" +
+ "EXCEPT\n" +
+ "SELECT user_id\n" +
+ "FROM (\n" +
+ "\tSELECT user_id, create_time, reg_channel, src, certified_from\n" +
+ "\t\t, certified_time, account_certify_type, is_certified, crm_label, order_cnt\n" +
+ "\t\t, cloud_order_cnt, cloud_market_order_cnt, count_ecs_paid_order, count_rds_paid_order, count_oss_paid_order\n" +
+ "\t\t, count_cdn_paid_order, count_slb_paid_order, count_nas_paid_order, count_mongodb_paid_order, count_eip_paid_order\n" +
+ "\t\t, count_redis_paid_order, count_communicate_paid_order\n" +
+ "\tFROM user_info_online\n" +
+ "\tWHERE user_id = 1953401122571952\n" +
+ "))\n" +
+ "UNION\n" +
+ "SELECT coalesce(a.user_id, b.user_id) AS user_id\n" +
+ "FROM (\n" +
+ "\tSELECT user_id, create_time, reg_channel, src, certified_from\n" +
+ "\t\t, certified_time, account_certify_type, is_certified, crm_label, order_cnt\n" +
+ "\t\t, cloud_order_cnt, cloud_market_order_cnt, count_ecs_paid_order, count_rds_paid_order, count_oss_paid_order\n" +
+ "\t\t, count_cdn_paid_order, count_slb_paid_order, count_nas_paid_order, count_mongodb_paid_order, count_eip_paid_order\n" +
+ "\t\t, count_redis_paid_order, count_communicate_paid_order\n" +
+ "\tFROM user_info_online\n" +
+ "\tWHERE user_id = 1953401122571952\n" +
+ ") a\n" +
+ "\tLEFT JOIN (\n" +
+ "\t\tSELECT user_id, havana_id, create_time, reg_days, own\n" +
+ "\t\t\t, reg_own_group, reg_src_group, reg_channel, src, global_city_name\n" +
+ "\t\t\t, locale, cid, cid_name, account_certify_type, certified_from\n" +
+ "\t\t\t, certified_time, certify_type, is_certified, account_type, address\n" +
+ "\t\t\t, age, sex, birthday, global_province_name, group_phone_area_no\n" +
+ "\t\t\t, group_phone_zone_no, l_level, crm_label, account_structure, account_frozen\n" +
+ "\t\t\t, hid_b2b, hid_taobao, is_aliyun_test_user, is_aliyun_user, is_enterprise\n" +
+ "\t\t\t, is_enterprise_account, is_global_user, is_net_test_user, is_oversea_user, is_valid_reg_user\n" +
+ "\t\t\t, is_net_user, parent_pk, taobao_account, update_time, user_region\n" +
+ "\t\t\t, fenxiao_create_time, fenxiao_label, fenxiao_parent_uid, fenxiao_region, crm_customer_priority\n" +
+ "\t\t\t, crm_customer_rank, order_cnt, cloud_order_cnt, cloud_market_order_cnt, count_ecs_paid_order\n" +
+ "\t\t\t, count_rds_paid_order, count_oss_paid_order, count_cdn_paid_order, count_slb_paid_order, count_nas_paid_order\n" +
+ "\t\t\t, count_mongodb_paid_order, count_eip_paid_order, count_redis_paid_order, count_communicate_paid_order, is_paid_retain\n" +
+ "\t\t\t, count_1_all_visit, count_7_all_visit, count_15_all_visit, count_30_all_visit, is_retain_d\n" +
+ "\t\t\t, count_1_yq_visit, count_7_yq_visit, count_15_yq_visit, count_30_yq_visit, count_1_promotion_visit\n" +
+ "\t\t\t, count_7_promotion_visit, count_15_promotion_visit, count_30_promotion_visit, count_1_market_visit, count_7_market_visit\n" +
+ "\t\t\t, count_15_market_visit, count_30_market_visit, count_1_search_visit, count_7_search_visit, count_15_search_visit\n" +
+ "\t\t\t, count_30_search_visit, count_1_help_visit, count_7_help_visit, count_15_help_visit, count_30_help_visit\n" +
+ "\t\t\t, count_7_domain_visit, count_15_domain_visit, count_30_domain_visit, count_1_beian_visit, count_7_beian_visit\n" +
+ "\t\t\t, count_15_beian_visit, count_30_beian_visit, count_1_wanwang_visit, count_7_wanwang_visit, count_15_wanwang_visit\n" +
+ "\t\t\t, count_30_wanwang_visit, count_1_domain_visit, crm_biz_category, cloud_pay_greater_zero_order_cnt, retain_cnt_d\n" +
+ "\t\t\t, retain_cnt_ecs_d, retain_cnt_rds_d, retain_cnt_oss_d, retain_cnt_cdn_d, retain_cnt_slb_d\n" +
+ "\t\t\t, retain_cnt_nas_d, retain_cnt_mangodb_d, retain_cnt_eip_d, retain_cnt_redis_d, retain_cnt_communication_d\n" +
+ "\t\t\t, retain_cnt_domain_d, retain_cnt_email_d, retain_cnt_dns_d\n" +
+ "\t\tFROM user_info_offline\n" +
+ "\t\tWHERE user_id = 1953401122571952\n" +
+ "\t) b\n" +
+ "\tON a.user_id = b.user_id\n" +
+ "WHERE a.create_time > '2018-01-01 00:00:00'\n" +
+ "\tOR (a.create_time IS NULL\n" +
+ "\t\tAND b.create_time > '2018-01-01 00:00:00'))\n" +
+ "INTERSECT\n" +
+ "(SELECT coalesce(a.user_id, b.user_id) AS user_id\n" +
+ "FROM (\n" +
+ "\tSELECT user_id, create_time, reg_channel, src, certified_from\n" +
+ "\t\t, certified_time, account_certify_type, is_certified, crm_label, order_cnt\n" +
+ "\t\t, cloud_order_cnt, cloud_market_order_cnt, count_ecs_paid_order, count_rds_paid_order, count_oss_paid_order\n" +
+ "\t\t, count_cdn_paid_order, count_slb_paid_order, count_nas_paid_order, count_mongodb_paid_order, count_eip_paid_order\n" +
+ "\t\t, count_redis_paid_order, count_communicate_paid_order\n" +
+ "\tFROM user_info_online\n" +
+ "\tWHERE user_id = 1953401122571952\n" +
+ ") a\n" +
+ "\tFULL JOIN (\n" +
+ "\t\tSELECT user_id, havana_id, create_time, reg_days, own\n" +
+ "\t\t\t, reg_own_group, reg_src_group, reg_channel, src, global_city_name\n" +
+ "\t\t\t, locale, cid, cid_name, account_certify_type, certified_from\n" +
+ "\t\t\t, certified_time, certify_type, is_certified, account_type, address\n" +
+ "\t\t\t, age, sex, birthday, global_province_name, group_phone_area_no\n" +
+ "\t\t\t, group_phone_zone_no, l_level, crm_label, account_structure, account_frozen\n" +
+ "\t\t\t, hid_b2b, hid_taobao, is_aliyun_test_user, is_aliyun_user, is_enterprise\n" +
+ "\t\t\t, is_enterprise_account, is_global_user, is_net_test_user, is_oversea_user, is_valid_reg_user\n" +
+ "\t\t\t, is_net_user, parent_pk, taobao_account, update_time, user_region\n" +
+ "\t\t\t, fenxiao_create_time, fenxiao_label, fenxiao_parent_uid, fenxiao_region, crm_customer_priority\n" +
+ "\t\t\t, crm_customer_rank, order_cnt, cloud_order_cnt, cloud_market_order_cnt, count_ecs_paid_order\n" +
+ "\t\t\t, count_rds_paid_order, count_oss_paid_order, count_cdn_paid_order, count_slb_paid_order, count_nas_paid_order\n" +
+ "\t\t\t, count_mongodb_paid_order, count_eip_paid_order, count_redis_paid_order, count_communicate_paid_order, is_paid_retain\n" +
+ "\t\t\t, count_1_all_visit, count_7_all_visit, count_15_all_visit, count_30_all_visit, is_retain_d\n" +
+ "\t\t\t, count_1_yq_visit, count_7_yq_visit, count_15_yq_visit, count_30_yq_visit, count_1_promotion_visit\n" +
+ "\t\t\t, count_7_promotion_visit, count_15_promotion_visit, count_30_promotion_visit, count_1_market_visit, count_7_market_visit\n" +
+ "\t\t\t, count_15_market_visit, count_30_market_visit, count_1_search_visit, count_7_search_visit, count_15_search_visit\n" +
+ "\t\t\t, count_30_search_visit, count_1_help_visit, count_7_help_visit, count_15_help_visit, count_30_help_visit\n" +
+ "\t\t\t, count_7_domain_visit, count_15_domain_visit, count_30_domain_visit, count_1_beian_visit, count_7_beian_visit\n" +
+ "\t\t\t, count_15_beian_visit, count_30_beian_visit, count_1_wanwang_visit, count_7_wanwang_visit, count_15_wanwang_visit\n" +
+ "\t\t\t, count_30_wanwang_visit, count_1_domain_visit, crm_biz_category, cloud_pay_greater_zero_order_cnt, retain_cnt_d\n" +
+ "\t\t\t, retain_cnt_ecs_d, retain_cnt_rds_d, retain_cnt_oss_d, retain_cnt_cdn_d, retain_cnt_slb_d\n" +
+ "\t\t\t, retain_cnt_nas_d, retain_cnt_mangodb_d, retain_cnt_eip_d, retain_cnt_redis_d, retain_cnt_communication_d\n" +
+ "\t\t\t, retain_cnt_domain_d, retain_cnt_email_d, retain_cnt_dns_d\n" +
+ "\t\tFROM user_info_offline\n" +
+ "\t\tWHERE user_id = 1953401122571952\n" +
+ "\t) b\n" +
+ "\tON a.user_id = b.user_id\n" +
+ "WHERE a.account_certify_type = 'personal'\n" +
+ "\tOR (a.account_certify_type IS NULL\n" +
+ "\t\tAND b.account_certify_type = 'personal'))", stmt.toString());
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/select/MySqlSelectTest_196_wall.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/select/MySqlSelectTest_196_wall.java
new file mode 100644
index 0000000000..ae4de33a0f
--- /dev/null
+++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/select/MySqlSelectTest_196_wall.java
@@ -0,0 +1,25 @@
+package com.alibaba.druid.bvt.sql.mysql.select;
+
+import com.alibaba.druid.sql.MysqlTest;
+import com.alibaba.druid.sql.ast.SQLStatement;
+import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;
+import com.alibaba.druid.sql.parser.ParserException;
+
+import java.util.List;
+
+public class MySqlSelectTest_196_wall extends MysqlTest {
+
+ public void test_0() throws Exception {
+ String sql = "update task_info set priority = 1, content = 'x渓螼h\u0013[\u0014\u0006饆蜭�)漉=灔�\u000B\u0011\u0011u�\uE06A圥Z[\u0017殞c怈﹝櫃&c摍0\u007Fj璟\u0004]JWRb峌膮埜\u0014譢\"瓺\\\\塼!.D牡玕\"邥\t� 佥篼緖.W=Rw4�\u001E3\t玭YF螭�\u0004�);\u0011�I\u0017�%\u0017谦漜f*\bm梄恀拒t)/�I�\"uSP蟉�\u0006I3\\\"�\u0016敐\f\\Z殷觀n\\\"餭讖;祵Y換g\uE5B7&柋\u0017�\u0011﹗A欍媞(I=\u0010�x鐹�\u000B!蜿\u0006\u0013�lQw�(33毳圳倀!\uE324=&释烃襲�&b\uE1EF�\u0013mm孺L\u0014嚍_MS7湏痘笫滴;y鶲\b爱骤求秩G-\u001By~殿揀\uE222�\u0003鮝[�Dqo:蟎'~=裼�\u001F垴蟵\\rY�\u0013.\uE3F9R\u000E�\u0012滂燶n鑲�\u0002贛龎=\u0010ミ�\u0007/%�\u001C癳c�\u000E\\Z旊\u001B�\u000B2栣玄岜�#cc吜\uE6C5�\u001B嚮醽nx�\u001B巘肅輕4E鎊\u0018E\u0018跴欱貯i\u0007蘉渚秘\u0007c\u00129狓\u0004F\u001F\f\u0013�觠3\u000B��-XS8�\u0010�\u0019V\u001E諭餸�\u000Fk\\r|\u0014V\u0005躒_A彙?E�*�\u0015琔�\u001Ep共\u000B�\u0006Z\u001F�%楳�\u001D\u001C玾郳\"\uE26B\u0011�\u0006Jj\u0016h\u0005�\u001C�\u0002�\u0002�\u0004j貌`.�\u0001�\u0005韁\"�\u0006z佉\u0012�\u001CxQ�\u0007\u0017@呃-斵曼\\0k砛0k\u0003鬨Z\uE5E9\u007F\u0006^�\u000Es\u0005欳B�\f\\0\\0��+僜'�', attribute = 0, create_time = from_unixtime(1531714297) where id = 2726633030";
+
+ Exception error = null;
+ try {
+ MySqlStatementParser parser = new MySqlStatementParser(sql);
+ List statementList = parser.parseStatementList();
+ } catch (ParserException ex) {
+ error = ex;
+ }
+
+ assertNotNull(error);
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/update/MySqlUpdateTest_17.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/update/MySqlUpdateTest_17.java
new file mode 100644
index 0000000000..b256dbda0a
--- /dev/null
+++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/update/MySqlUpdateTest_17.java
@@ -0,0 +1,77 @@
+/*
+ * 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.update;
+
+import com.alibaba.druid.sql.MysqlTest;
+import com.alibaba.druid.sql.SQLUtils;
+import com.alibaba.druid.sql.ast.SQLExpr;
+import com.alibaba.druid.sql.ast.SQLStatement;
+import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement;
+import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;
+import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;
+import com.alibaba.druid.stat.TableStat.Column;
+import com.alibaba.druid.wall.WallUtils;
+
+import java.util.List;
+
+public class MySqlUpdateTest_17 extends MysqlTest {
+
+ public void test_0() throws Exception {
+ String sql = "update security_group_ip_count set ip_count=GREATEST(ip_count-?, 0), gmt_modified=now() where group_id=? ";
+
+ MySqlStatementParser parser = new MySqlStatementParser(sql);
+ List statementList = parser.parseStatementList();
+ SQLStatement stmt = statementList.get(0);
+ print(statementList);
+
+ assertEquals(1, statementList.size());
+
+ MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();
+ 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(3, visitor.getColumns().size());
+ // assertEquals(2, visitor.getConditions().size());
+
+ assertTrue(visitor.containsTable("security_group_ip_count"));
+
+ assertTrue(visitor.getColumns().contains(new Column("security_group_ip_count", "ip_count")));
+
+ assertEquals("UPDATE security_group_ip_count\n" +
+ "SET ip_count = GREATEST(ip_count - ?, 0), gmt_modified = now()\n" +
+ "WHERE group_id = ?", //
+ stmt.toString());
+ assertEquals("update security_group_ip_count\n" +
+ "set ip_count = GREATEST(ip_count - ?, 0), gmt_modified = now()\n" +
+ "where group_id = ?", //
+ stmt.toLowerCaseString());
+
+
+ assertTrue(WallUtils.isValidateMySql(sql));
+
+ {
+ SQLUpdateStatement update = (SQLUpdateStatement) stmt;
+ SQLExpr where = update.getWhere();
+ assertEquals("group_id = ?", where.toString());
+ }
+
+ }
+}
diff --git a/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerUpdateTest6.java b/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerUpdateTest6.java
new file mode 100644
index 0000000000..5e47cf8c6e
--- /dev/null
+++ b/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerUpdateTest6.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.bvt.sql.sqlserver;
+
+import com.alibaba.druid.sql.ast.SQLStatement;
+import com.alibaba.druid.sql.dialect.sqlserver.parser.SQLServerStatementParser;
+import junit.framework.TestCase;
+
+public class SQLServerUpdateTest6 extends TestCase {
+
+ public void test_update() throws Exception {
+ String sql = "update clients set name =N'小明',age =1";
+
+ String expect = "UPDATE TOP (10) HumanResources.Employee"
+ + "\nSET VacationHours = VacationHours * 1.25, ModifiedDate = GETDATE()"
+ + "\nOUTPUT inserted.BusinessEntityID, deleted.VacationHours, inserted.VacationHours, inserted.ModifiedDate"
+ + "\n\tINTO @MyTableVar;";
+
+
+ SQLServerStatementParser parser = new SQLServerStatementParser(sql);
+ SQLStatement stmt = parser.parseStatementList().get(0);
+
+ assertEquals("UPDATE clients\n" +
+ "SET name = N'小明', age = 1", stmt.toString());
+ }
+}