diff --git a/pom.xml b/pom.xml
index e4f09f1748..e164e39b24 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,7 +3,7 @@
4.0.0
com.alibaba
druid
- 1.1.5-SNAPSHOT
+ 1.1.5-preview_05
jar
druid
@@ -279,6 +279,7 @@
1.6.0
system
${java.home}/../Classes/jconsole.jar
+ true
@@ -298,6 +299,7 @@
1.8.0
system
${java.home}/../lib/jconsole.jar
+ true
@@ -306,6 +308,7 @@
1.8.0
system
${java.home}/../lib/tools.jar
+ true
@@ -540,7 +543,7 @@
org.apache.calcite
calcite-core
- 1.13.0
+ 1.14.0
provided
@@ -706,6 +709,12 @@
1.2.36
test
+
+ org.antlr
+ antlr4
+ 4.7
+ test
+
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 45e76bc842..dcbf499221 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
@@ -248,7 +248,7 @@ public class SQLAggregateExpr extends SQLExprImpl implements Serializable, SQLRe
}
}
- if (hash == FnvHash.Constants.WM_CONAT
+ if (hash == FnvHash.Constants.WM_CONCAT
|| hash == FnvHash.Constants.GROUP_CONCAT) {
return SQLCharExpr.DEFAULT_DATA_TYPE;
}
diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLIntervalExpr.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLIntervalExpr.java
index d7be259c99..1a8d782370 100644
--- a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLIntervalExpr.java
+++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLIntervalExpr.java
@@ -25,11 +25,16 @@ import java.util.List;
public class SQLIntervalExpr extends SQLExprImpl {
private SQLExpr value;
- private SQLIntervalUnit unit;
+ private SQLIntervalUnit unit;
public SQLIntervalExpr(){
}
+ public SQLIntervalExpr(SQLExpr value, SQLIntervalUnit unit){
+ setValue(value);
+ this.unit = unit;
+ }
+
public SQLIntervalExpr clone() {
SQLIntervalExpr x = new SQLIntervalExpr();
if (value != null) {
diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLUnionQuery.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLUnionQuery.java
index 7911aeb836..91b479a71d 100644
--- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLUnionQuery.java
+++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLUnionQuery.java
@@ -15,9 +15,11 @@
*/
package com.alibaba.druid.sql.ast.statement;
+import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLLimit;
import com.alibaba.druid.sql.ast.SQLObjectImpl;
import com.alibaba.druid.sql.ast.SQLOrderBy;
+import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
public class SQLUnionQuery extends SQLObjectImpl implements SQLSelectQuery {
@@ -29,7 +31,8 @@ public class SQLUnionQuery extends SQLObjectImpl implements SQLSelectQuery {
private SQLUnionOperator operator = SQLUnionOperator.UNION;
private SQLOrderBy orderBy;
- private SQLLimit limit;
+ private SQLLimit limit;
+ private String dbType;
public SQLUnionOperator getOperator() {
return operator;
@@ -133,6 +136,8 @@ public class SQLUnionQuery extends SQLObjectImpl implements SQLSelectQuery {
x.setLimit(limit.clone());
}
+ x.dbType = dbType;
+
return x;
}
@@ -147,4 +152,17 @@ public class SQLUnionQuery extends SQLObjectImpl implements SQLSelectQuery {
return null;
}
+
+ public String getDbType() {
+ return dbType;
+ }
+
+ public void setDbType(String dbType) {
+ this.dbType = dbType;
+ }
+
+ public void output(StringBuffer buf) {
+ SQLASTOutputVisitor visitor = SQLUtils.createOutputVisitor(buf, dbType);
+ this.accept(visitor);
+ }
}
diff --git a/src/main/java/com/alibaba/druid/sql/dialect/db2/ast/DB2Object.java b/src/main/java/com/alibaba/druid/sql/dialect/db2/ast/DB2Object.java
index f787045b70..c6c8dcf055 100644
--- a/src/main/java/com/alibaba/druid/sql/dialect/db2/ast/DB2Object.java
+++ b/src/main/java/com/alibaba/druid/sql/dialect/db2/ast/DB2Object.java
@@ -17,8 +17,14 @@ package com.alibaba.druid.sql.dialect.db2.ast;
import com.alibaba.druid.sql.ast.SQLObject;
import com.alibaba.druid.sql.dialect.db2.visitor.DB2ASTVisitor;
+import com.alibaba.druid.util.FnvHash;
public interface DB2Object extends SQLObject {
void accept0(DB2ASTVisitor visitor);
+
+ interface Constants {
+ long CURRENT_DATE = FnvHash.fnv1a_64_lower("CURRENT DATE");
+ long CURRENT_TIME = FnvHash.fnv1a_64_lower("CURRENT TIME");
+ }
}
diff --git a/src/main/java/com/alibaba/druid/sql/dialect/db2/parser/DB2ExprParser.java b/src/main/java/com/alibaba/druid/sql/dialect/db2/parser/DB2ExprParser.java
index 9b7f5d1cfe..69e9a44c33 100644
--- a/src/main/java/com/alibaba/druid/sql/dialect/db2/parser/DB2ExprParser.java
+++ b/src/main/java/com/alibaba/druid/sql/dialect/db2/parser/DB2ExprParser.java
@@ -18,6 +18,8 @@ package com.alibaba.druid.sql.dialect.db2.parser;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLName;
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
+import com.alibaba.druid.sql.ast.expr.SQLIntervalExpr;
+import com.alibaba.druid.sql.ast.expr.SQLIntervalUnit;
import com.alibaba.druid.sql.ast.expr.SQLSequenceExpr;
import com.alibaba.druid.sql.parser.Lexer;
import com.alibaba.druid.sql.parser.SQLExprParser;
@@ -93,9 +95,42 @@ public class DB2ExprParser extends SQLExprParser {
if (identExpr.hashCode64() == FnvHash.Constants.CURRENT) {
lexer.nextToken();
- expr = new SQLIdentifierExpr("CURRENT DATE");
+ expr = new SQLIdentifierExpr("CURRENT TIMESTAMP");
}
}
+ } else if (lexer.identifierEquals(FnvHash.Constants.TIME)) {
+ if (expr instanceof SQLIdentifierExpr) {
+ SQLIdentifierExpr identExpr = (SQLIdentifierExpr) expr;
+ if (identExpr.hashCode64() == FnvHash.Constants.CURRENT) {
+ lexer.nextToken();
+
+ expr = new SQLIdentifierExpr("CURRENT TIME");
+ }
+ }
+ } else if (lexer.identifierEquals(FnvHash.Constants.MONTHS)) {
+ SQLIntervalExpr intervalExpr = new SQLIntervalExpr(expr, SQLIntervalUnit.MONTH);
+ lexer.nextToken();
+ expr = intervalExpr;
+ } else if (lexer.identifierEquals(FnvHash.Constants.YEARS)) {
+ SQLIntervalExpr intervalExpr = new SQLIntervalExpr(expr, SQLIntervalUnit.YEAR);
+ lexer.nextToken();
+ expr = intervalExpr;
+ } else if (lexer.identifierEquals(FnvHash.Constants.DAYS)) {
+ SQLIntervalExpr intervalExpr = new SQLIntervalExpr(expr, SQLIntervalUnit.DAY);
+ lexer.nextToken();
+ expr = intervalExpr;
+ } else if (lexer.identifierEquals(FnvHash.Constants.HOURS)) {
+ SQLIntervalExpr intervalExpr = new SQLIntervalExpr(expr, SQLIntervalUnit.HOUR);
+ lexer.nextToken();
+ expr = intervalExpr;
+ } else if (lexer.identifierEquals(FnvHash.Constants.MINUTES)) {
+ SQLIntervalExpr intervalExpr = new SQLIntervalExpr(expr, SQLIntervalUnit.MINUTE);
+ lexer.nextToken();
+ expr = intervalExpr;
+ } else if (lexer.identifierEquals(FnvHash.Constants.SECONDS)) {
+ SQLIntervalExpr intervalExpr = new SQLIntervalExpr(expr, SQLIntervalUnit.SECOND);
+ lexer.nextToken();
+ expr = intervalExpr;
}
return super.primaryRest(expr);
diff --git a/src/main/java/com/alibaba/druid/sql/dialect/db2/parser/DB2SelectParser.java b/src/main/java/com/alibaba/druid/sql/dialect/db2/parser/DB2SelectParser.java
index 26a016eafc..b71c77d421 100644
--- a/src/main/java/com/alibaba/druid/sql/dialect/db2/parser/DB2SelectParser.java
+++ b/src/main/java/com/alibaba/druid/sql/dialect/db2/parser/DB2SelectParser.java
@@ -22,15 +22,18 @@ import com.alibaba.druid.sql.ast.statement.SQLSelectQuery;
import com.alibaba.druid.sql.dialect.db2.ast.stmt.DB2SelectQueryBlock;
import com.alibaba.druid.sql.dialect.db2.ast.stmt.DB2SelectQueryBlock.Isolation;
import com.alibaba.druid.sql.parser.*;
+import com.alibaba.druid.util.JdbcConstants;
public class DB2SelectParser extends SQLSelectParser {
public DB2SelectParser(SQLExprParser exprParser){
super(exprParser);
+ dbType = JdbcConstants.DB2;
}
public DB2SelectParser(SQLExprParser exprParser, SQLSelectListCache selectListCache){
super(exprParser, selectListCache);
+ dbType = JdbcConstants.DB2;
}
public DB2SelectParser(String sql){
diff --git a/src/main/java/com/alibaba/druid/sql/dialect/db2/visitor/DB2OutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/db2/visitor/DB2OutputVisitor.java
index ddd07192bb..e591c4d62c 100644
--- a/src/main/java/com/alibaba/druid/sql/dialect/db2/visitor/DB2OutputVisitor.java
+++ b/src/main/java/com/alibaba/druid/sql/dialect/db2/visitor/DB2OutputVisitor.java
@@ -15,9 +15,12 @@
*/
package com.alibaba.druid.sql.dialect.db2.visitor;
+import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLName;
import com.alibaba.druid.sql.ast.SQLPartitionBy;
import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator;
+import com.alibaba.druid.sql.ast.expr.SQLIntervalExpr;
+import com.alibaba.druid.sql.ast.expr.SQLIntervalUnit;
import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
import com.alibaba.druid.sql.dialect.db2.ast.stmt.DB2CreateTableStatement;
@@ -143,4 +146,17 @@ public class DB2OutputVisitor extends SQLASTOutputVisitor implements DB2ASTVisit
print0(ucase ? operator.name : operator.name_lcase);
}
}
+
+ public boolean visit(SQLIntervalExpr x) {
+ SQLExpr value = x.getValue();
+ value.accept(this);
+
+ SQLIntervalUnit unit = x.getUnit();
+ if (unit != null) {
+ print(' ');
+ print0(ucase ? unit.name() : unit.name_lcase);
+ print(ucase ? 'S' : 's');
+ }
+ return false;
+ }
}
diff --git a/src/main/java/com/alibaba/druid/sql/dialect/db2/visitor/DB2SchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/db2/visitor/DB2SchemaStatVisitor.java
index 12568e1c13..266f16e52f 100644
--- a/src/main/java/com/alibaba/druid/sql/dialect/db2/visitor/DB2SchemaStatVisitor.java
+++ b/src/main/java/com/alibaba/druid/sql/dialect/db2/visitor/DB2SchemaStatVisitor.java
@@ -17,6 +17,7 @@ package com.alibaba.druid.sql.dialect.db2.visitor;
import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
+import com.alibaba.druid.sql.dialect.db2.ast.DB2Object;
import com.alibaba.druid.sql.dialect.db2.ast.stmt.DB2CreateTableStatement;
import com.alibaba.druid.sql.dialect.db2.ast.stmt.DB2SelectQueryBlock;
import com.alibaba.druid.sql.dialect.db2.ast.stmt.DB2ValuesStatement;
@@ -57,4 +58,8 @@ public class DB2SchemaStatVisitor extends SchemaStatVisitor implements DB2ASTVis
public void endVisit(DB2CreateTableStatement x) {
}
+
+ protected boolean isPseudoColumn(long hash64) {
+ return hash64 == DB2Object.Constants.CURRENT_DATE || hash64 == DB2Object.Constants.CURRENT_TIME;
+ }
}
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 8eebcb2cbb..acdd191592 100644
--- a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java
+++ b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java
@@ -1035,7 +1035,7 @@ public class SQLExprParser extends SQLParser {
}
if (lexer.token == Token.LPAREN) {
- expr = methodRest(expr, name);
+ expr = methodRest(expr, name, false);
} else {
expr = new SQLPropertyExpr(expr, name, hash_lower);
}
@@ -1045,7 +1045,7 @@ public class SQLExprParser extends SQLParser {
return expr;
}
- private SQLExpr methodRest(SQLExpr expr, String name) {
+ private SQLExpr methodRest(SQLExpr expr, String name, boolean aggregate) {
lexer.nextToken();
if (lexer.token == Token.DISTINCT) {
@@ -1066,6 +1066,21 @@ public class SQLExprParser extends SQLParser {
accept(Token.RPAREN);
}
expr = aggregateExpr;
+ } else if (aggregate) {
+ SQLAggregateExpr methodInvokeExpr = new SQLAggregateExpr(name);
+ methodInvokeExpr.setMethodName(expr.toString() + "." + name);
+ if (lexer.token == Token.RPAREN) {
+ lexer.nextToken();
+ } else {
+ if (lexer.token == Token.PLUS) {
+ methodInvokeExpr.addArgument(new SQLIdentifierExpr("+"));
+ lexer.nextToken();
+ } else {
+ exprList(methodInvokeExpr.getArguments(), methodInvokeExpr);
+ }
+ accept(Token.RPAREN);
+ }
+ expr = methodInvokeExpr;
} else {
SQLMethodInvokeExpr methodInvokeExpr = new SQLMethodInvokeExpr(name);
methodInvokeExpr.setOwner(expr);
@@ -2657,7 +2672,8 @@ public class SQLExprParser extends SQLParser {
token = lexer.token;
if (token == Token.LPAREN) {
- expr = methodRest(expr, name);
+ boolean aggregate = hash_lower == FnvHash.Constants.WMSYS && name_hash_lower == FnvHash.Constants.WM_CONCAT;
+ expr = methodRest(expr, name, aggregate);
token = lexer.token;
} else {
if (name_hash_lower == FnvHash.Constants.NEXTVAL) {
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 ff2125a599..a59abac197 100644
--- a/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java
+++ b/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java
@@ -84,7 +84,9 @@ public class SQLSelectParser extends SQLParser {
}
protected SQLUnionQuery createSQLUnionQuery() {
- return new SQLUnionQuery();
+ SQLUnionQuery union = new SQLUnionQuery();
+ union.setDbType(getDbType());
+ return union;
}
public SQLUnionQuery unionRest(SQLUnionQuery union) {
diff --git a/src/main/java/com/alibaba/druid/sql/repository/SchemaResolveVisitorFactory.java b/src/main/java/com/alibaba/druid/sql/repository/SchemaResolveVisitorFactory.java
index 4ca43aae91..4504318206 100644
--- a/src/main/java/com/alibaba/druid/sql/repository/SchemaResolveVisitorFactory.java
+++ b/src/main/java/com/alibaba/druid/sql/repository/SchemaResolveVisitorFactory.java
@@ -19,6 +19,7 @@ import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.*;
import com.alibaba.druid.sql.ast.expr.*;
import com.alibaba.druid.sql.ast.statement.*;
+import com.alibaba.druid.sql.dialect.db2.ast.DB2Object;
import com.alibaba.druid.sql.dialect.db2.ast.stmt.DB2SelectQueryBlock;
import com.alibaba.druid.sql.dialect.db2.visitor.DB2ASTVisitorAdapter;
import com.alibaba.druid.sql.dialect.mysql.ast.MysqlForeignKey;
@@ -230,8 +231,6 @@ class SchemaResolveVisitorFactory {
}
}
-
-
static class DB2ResolveVisitor extends DB2ASTVisitorAdapter implements SchemaResolveVisitor {
private SchemaRepository repository;
private int options;
@@ -283,6 +282,11 @@ class SchemaResolveVisitorFactory {
}
public boolean visit(SQLIdentifierExpr x) {
+ long hash64 = x.hashCode64();
+ if (hash64 == DB2Object.Constants.CURRENT_DATE || hash64 == DB2Object.Constants.CURRENT_TIME) {
+ return false;
+ }
+
resolve(this, x);
return true;
}
@@ -1684,7 +1688,7 @@ class SchemaResolveVisitorFactory {
if (ctxTable instanceof SQLJoinTableSource) {
String alias = tableSource.computeAlias();
- if (alias == null) {
+ if (alias == null || tableSource instanceof SQLWithSubqueryClause.Entry) {
return;
}
diff --git a/src/main/java/com/alibaba/druid/util/FnvHash.java b/src/main/java/com/alibaba/druid/util/FnvHash.java
index 1a187a6ad5..6e6a4424b2 100644
--- a/src/main/java/com/alibaba/druid/util/FnvHash.java
+++ b/src/main/java/com/alibaba/druid/util/FnvHash.java
@@ -350,6 +350,7 @@ public final class FnvHash {
long DATE = fnv1a_64_lower("DATE");
long DATETIME = fnv1a_64_lower("DATETIME");
+ long TIME = fnv1a_64_lower("TIME");
long TIMESTAMP = fnv1a_64_lower("TIMESTAMP");
long CLOB = fnv1a_64_lower("CLOB");
long NCLOB = fnv1a_64_lower("NCLOB");
@@ -371,7 +372,7 @@ public final class FnvHash {
long CURRENT = fnv1a_64_lower("CURRENT");
long COUNT = fnv1a_64_lower("COUNT");
long ROW_NUMBER = fnv1a_64_lower("ROW_NUMBER");
- long WM_CONAT = fnv1a_64_lower("WM_CONAT");
+ long WM_CONCAT = fnv1a_64_lower("WM_CONCAT");
long AVG = fnv1a_64_lower("AVG");
long MAX = fnv1a_64_lower("MAX");
long MIN = fnv1a_64_lower("MIN");
@@ -472,6 +473,13 @@ public final class FnvHash {
long MINUTE = fnv1a_64_lower("MINUTE");
long SECOND = fnv1a_64_lower("SECOND");
+ long SECONDS = fnv1a_64_lower("SECONDS");
+ long MINUTES = fnv1a_64_lower("MINUTES");
+ long HOURS = fnv1a_64_lower("HOURS");
+ long DAYS = fnv1a_64_lower("DAYS");
+ long MONTHS = fnv1a_64_lower("MONTHS");
+ long YEARS = fnv1a_64_lower("YEARS");
+
long BEFORE = fnv1a_64_lower("BEFORE");
long AFTER = fnv1a_64_lower("AFTER");
long INSTEAD = fnv1a_64_lower("INSTEAD");
@@ -515,5 +523,6 @@ public final class FnvHash {
long VALIDPROC = fnv1a_64_lower("VALIDPROC");
long COMPRESS = fnv1a_64_lower("COMPRESS");
long YES = fnv1a_64_lower("YES");
+ long WMSYS = fnv1a_64_lower("WMSYS");
}
}
diff --git a/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SelectTest_26.java b/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SelectTest_26.java
new file mode 100644
index 0000000000..a82e3824f9
--- /dev/null
+++ b/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SelectTest_26.java
@@ -0,0 +1,170 @@
+/*
+ * 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.db2;
+
+import com.alibaba.druid.sql.DB2Test;
+import com.alibaba.druid.sql.SQLUtils;
+import com.alibaba.druid.sql.ast.SQLStatement;
+import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
+import com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;
+import com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;
+import com.alibaba.druid.stat.TableStat;
+import com.alibaba.druid.util.JdbcConstants;
+import org.junit.Assert;
+
+import java.util.List;
+
+public class DB2SelectTest_26 extends DB2Test {
+
+ public void test_0() throws Exception {
+ String sql = "SELECT LATN_ID,\n" +
+ "CASE WHEN BUREAU_KEY = 116 THEN 46 ELSE BUREAU_KEY END BUREAU_KEY,\n" +
+ "SUM(COALESCE(ADD_USER_CNT, 0)) ADD_SUM,\n" +
+ "0 USER_ACCT,\n" +
+ "0 USER_ACCT_LY\n" +
+ "FROM MK.M_BROAD_BAND_USER_FACT\n" +
+ "WHERE THE_DATE BETWEEN SUBSTR('{THISMONTH}', 1, 4) || '-01-01' AND '{THISMONTH}'\n" +
+ "GROUP BY LATN_ID,\n" +
+ "CASE WHEN BUREAU_KEY = 116 THEN 46 ELSE BUREAU_KEY END\n" +
+ "UNION ALL\n" +
+ "SELECT LATN_ID,\n" +
+ "CASE WHEN BUREAU_KEY = 116 THEN 46 ELSE BUREAU_KEY END BUREAU_KEY,\n" +
+ "0 ADD_SUM,\n" +
+ "SUM(COALESCE(BILL_USER_CNT, 0)) USER_ACCT,\n" +
+ "0 USER_ACCT_LY\n" +
+ "FROM MK.M_BROAD_BAND_USER_FACT\n" +
+ "WHERE THE_DATE = '{THISMONTH}'\n" +
+ "GROUP BY LATN_ID,\n" +
+ "CASE WHEN BUREAU_KEY = 116 THEN 46 ELSE BUREAU_KEY END\n" +
+ "UNION ALL\n" +
+ "SELECT LATN_ID,\n" +
+ "CASE WHEN BUREAU_KEY = 116 THEN 46 ELSE BUREAU_KEY END BUREAU_KEY,\n" +
+ "0 ADD_SUM,\n" +
+ "0 USER_ACCT,\n" +
+ "SUM(COALESCE(BILL_USER_CNT, 0)) USER_ACCT_LY\n" +
+ "FROM MK.M_BROAD_BAND_USER_FACT\n" +
+ "WHERE THE_DATE = DATE(SUBSTR('{THISMONTH}', 1, 4) || '-01-01') - 1 MONTHS\n" +
+ "GROUP BY LATN_ID,\n" +
+ "CASE WHEN BUREAU_KEY = 116 THEN 46 ELSE BUREAU_KEY END";
+
+ DB2StatementParser parser = new DB2StatementParser(sql);
+ List statementList = parser.parseStatementList();
+ SQLSelectStatement stmt = (SQLSelectStatement) statementList.get(0);
+ System.out.println(stmt.getSelect().getQuery());
+
+ Assert.assertEquals(1, statementList.size());
+
+ DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();
+ 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(5, visitor.getColumns().size());
+ Assert.assertEquals(2, visitor.getConditions().size());
+
+ Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("MK.M_BROAD_BAND_USER_FACT")));
+
+// Assert.assertTrue(visitor.getColumns().contains(new Column("DSN8B10.EMP", "WORKDEPT")));
+ // Assert.assertTrue(visitor.getColumns().contains(new Column("mytable", "first_name")));
+ // Assert.assertTrue(visitor.getColumns().contains(new Column("mytable", "full_name")));
+
+ Assert.assertEquals("SELECT LATN_ID\n" +
+ "\t, CASE \n" +
+ "\t\tWHEN BUREAU_KEY = 116 THEN 46\n" +
+ "\t\tELSE BUREAU_KEY\n" +
+ "\tEND AS BUREAU_KEY, SUM(COALESCE(ADD_USER_CNT, 0)) AS ADD_SUM\n" +
+ "\t, 0 AS USER_ACCT, 0 AS USER_ACCT_LY\n" +
+ "FROM MK.M_BROAD_BAND_USER_FACT\n" +
+ "WHERE THE_DATE BETWEEN SUBSTR('{THISMONTH}', 1, 4) CONCAT '-01-01' AND '{THISMONTH}'\n" +
+ "GROUP BY LATN_ID, CASE \n" +
+ "\t\tWHEN BUREAU_KEY = 116 THEN 46\n" +
+ "\t\tELSE BUREAU_KEY\n" +
+ "\tEND\n" +
+ "UNION ALL\n" +
+ "SELECT LATN_ID\n" +
+ "\t, CASE \n" +
+ "\t\tWHEN BUREAU_KEY = 116 THEN 46\n" +
+ "\t\tELSE BUREAU_KEY\n" +
+ "\tEND AS BUREAU_KEY, 0 AS ADD_SUM\n" +
+ "\t, SUM(COALESCE(BILL_USER_CNT, 0)) AS USER_ACCT\n" +
+ "\t, 0 AS USER_ACCT_LY\n" +
+ "FROM MK.M_BROAD_BAND_USER_FACT\n" +
+ "WHERE THE_DATE = '{THISMONTH}'\n" +
+ "GROUP BY LATN_ID, CASE \n" +
+ "\t\tWHEN BUREAU_KEY = 116 THEN 46\n" +
+ "\t\tELSE BUREAU_KEY\n" +
+ "\tEND\n" +
+ "UNION ALL\n" +
+ "SELECT LATN_ID\n" +
+ "\t, CASE \n" +
+ "\t\tWHEN BUREAU_KEY = 116 THEN 46\n" +
+ "\t\tELSE BUREAU_KEY\n" +
+ "\tEND AS BUREAU_KEY, 0 AS ADD_SUM, 0 AS USER_ACCT\n" +
+ "\t, SUM(COALESCE(BILL_USER_CNT, 0)) AS USER_ACCT_LY\n" +
+ "FROM MK.M_BROAD_BAND_USER_FACT\n" +
+ "WHERE THE_DATE = DATE(SUBSTR('{THISMONTH}', 1, 4) CONCAT '-01-01') - 1 MONTHS\n" +
+ "GROUP BY LATN_ID, CASE \n" +
+ "\t\tWHEN BUREAU_KEY = 116 THEN 46\n" +
+ "\t\tELSE BUREAU_KEY\n" +
+ "\tEND", //
+ SQLUtils.toSQLString(stmt, JdbcConstants.DB2));
+
+ Assert.assertEquals("select LATN_ID\n" +
+ "\t, case \n" +
+ "\t\twhen BUREAU_KEY = 116 then 46\n" +
+ "\t\telse BUREAU_KEY\n" +
+ "\tend as BUREAU_KEY, sum(COALESCE(ADD_USER_CNT, 0)) as ADD_SUM\n" +
+ "\t, 0 as USER_ACCT, 0 as USER_ACCT_LY\n" +
+ "from MK.M_BROAD_BAND_USER_FACT\n" +
+ "where THE_DATE between SUBSTR('{THISMONTH}', 1, 4) concat '-01-01' and '{THISMONTH}'\n" +
+ "group by LATN_ID, case \n" +
+ "\t\twhen BUREAU_KEY = 116 then 46\n" +
+ "\t\telse BUREAU_KEY\n" +
+ "\tend\n" +
+ "union all\n" +
+ "select LATN_ID\n" +
+ "\t, case \n" +
+ "\t\twhen BUREAU_KEY = 116 then 46\n" +
+ "\t\telse BUREAU_KEY\n" +
+ "\tend as BUREAU_KEY, 0 as ADD_SUM\n" +
+ "\t, sum(COALESCE(BILL_USER_CNT, 0)) as USER_ACCT\n" +
+ "\t, 0 as USER_ACCT_LY\n" +
+ "from MK.M_BROAD_BAND_USER_FACT\n" +
+ "where THE_DATE = '{THISMONTH}'\n" +
+ "group by LATN_ID, case \n" +
+ "\t\twhen BUREAU_KEY = 116 then 46\n" +
+ "\t\telse BUREAU_KEY\n" +
+ "\tend\n" +
+ "union all\n" +
+ "select LATN_ID\n" +
+ "\t, case \n" +
+ "\t\twhen BUREAU_KEY = 116 then 46\n" +
+ "\t\telse BUREAU_KEY\n" +
+ "\tend as BUREAU_KEY, 0 as ADD_SUM, 0 as USER_ACCT\n" +
+ "\t, sum(COALESCE(BILL_USER_CNT, 0)) as USER_ACCT_LY\n" +
+ "from MK.M_BROAD_BAND_USER_FACT\n" +
+ "where THE_DATE = DATE(SUBSTR('{THISMONTH}', 1, 4) concat '-01-01') - 1 months\n" +
+ "group by LATN_ID, case \n" +
+ "\t\twhen BUREAU_KEY = 116 then 46\n" +
+ "\t\telse BUREAU_KEY\n" +
+ "\tend", //
+ SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));
+ }
+}
diff --git a/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SelectTest_27_interval.java b/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SelectTest_27_interval.java
new file mode 100644
index 0000000000..6c1e0629f4
--- /dev/null
+++ b/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2SelectTest_27_interval.java
@@ -0,0 +1,72 @@
+/*
+ * 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.db2;
+
+import com.alibaba.druid.sql.DB2Test;
+import com.alibaba.druid.sql.SQLUtils;
+import com.alibaba.druid.sql.ast.SQLStatement;
+import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
+import com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;
+import com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;
+import com.alibaba.druid.stat.TableStat;
+import com.alibaba.druid.util.JdbcConstants;
+import org.junit.Assert;
+
+import java.util.List;
+
+public class DB2SelectTest_27_interval extends DB2Test {
+
+ public void test_0() throws Exception {
+ String sql = "SELECT current date + 1 YEAR, current date + 3 YEARS + 2 MONTHS + 15 DAYS, current time + 5 HOURS - 3 MINUTES + 10 SECONDS from sysibm.sysdummy1";
+
+ DB2StatementParser parser = new DB2StatementParser(sql);
+ List statementList = parser.parseStatementList();
+ SQLSelectStatement stmt = (SQLSelectStatement) statementList.get(0);
+ System.out.println(stmt.getSelect().getQuery());
+
+ Assert.assertEquals(1, statementList.size());
+
+ DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor();
+ 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(0, visitor.getColumns().size());
+ Assert.assertEquals(0, visitor.getConditions().size());
+
+ Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("sysibm.sysdummy1")));
+
+// Assert.assertTrue(visitor.getColumns().contains(new Column("DSN8B10.EMP", "WORKDEPT")));
+ // Assert.assertTrue(visitor.getColumns().contains(new Column("mytable", "first_name")));
+ // Assert.assertTrue(visitor.getColumns().contains(new Column("mytable", "full_name")));
+
+ Assert.assertEquals("SELECT CURRENT DATE + 1 AS YEAR\n" +
+ "\t, CURRENT DATE + 3 YEARS + 2 MONTHS + 15 DAYS\n" +
+ "\t, CURRENT TIME + 5 HOURS - 3 MINUTES + 10 SECONDS\n" +
+ "FROM sysibm.sysdummy1", //
+ SQLUtils.toSQLString(stmt, JdbcConstants.DB2));
+
+ Assert.assertEquals("select CURRENT DATE + 1 as YEAR\n" +
+ "\t, CURRENT DATE + 3 years + 2 months + 15 days\n" +
+ "\t, CURRENT TIME + 5 hours - 3 minutes + 10 seconds\n" +
+ "from sysibm.sysdummy1", //
+ SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));
+ }
+}