improved db2 sql parser, support db2 interval expr. for issue #2037

This commit is contained in:
wenshao
2017-10-11 10:09:50 +08:00
parent cef99c1738
commit abad78e4a3
15 changed files with 384 additions and 14 deletions
+11 -2
View File
@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.5-SNAPSHOT</version>
<version>1.1.5-preview_05</version>
<packaging>jar</packaging>
<name>druid</name>
@@ -279,6 +279,7 @@
<version>1.6.0</version>
<scope>system</scope>
<systemPath>${java.home}/../Classes/jconsole.jar</systemPath>
<optional>true</optional>
</dependency>
</dependencies>
</profile>
@@ -298,6 +299,7 @@
<version>1.8.0</version>
<scope>system</scope>
<systemPath>${java.home}/../lib/jconsole.jar</systemPath>
<optional>true</optional>
</dependency>
<dependency>
@@ -306,6 +308,7 @@
<version>1.8.0</version>
<scope>system</scope>
<systemPath>${java.home}/../lib/tools.jar</systemPath>
<optional>true</optional>
</dependency>
</dependencies>
</profile>
@@ -540,7 +543,7 @@
<dependency>
<groupId>org.apache.calcite</groupId>
<artifactId>calcite-core</artifactId>
<version>1.13.0</version>
<version>1.14.0</version>
<scope>provided</scope>
</dependency>
<dependency>
@@ -706,6 +709,12 @@
<version>1.2.36</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr4</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
@@ -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;
}
@@ -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) {
@@ -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);
}
}
@@ -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");
}
}
@@ -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);
@@ -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){
@@ -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;
}
}
@@ -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;
}
}
@@ -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) {
@@ -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) {
@@ -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;
}
@@ -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");
}
}
@@ -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<SQLStatement> 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));
}
}
@@ -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<SQLStatement> 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));
}
}