From c21bcfc9e42f3ac78c4e571bb7c4178d4fe5413a Mon Sep 17 00:00:00 2001 From: Louis Xu Date: Tue, 29 Mar 2016 19:01:52 +0800 Subject: [PATCH] Add support for Teradata interval --- .../ast/expr/TeradataIntervalExpr.java | 78 +++++++++++++++++++ .../ast/expr/TeradataIntervalUnit.java | 14 ++++ .../teradata/parser/TeradataExprParser.java | 30 ++++++- .../teradata/visitor/TeradataASTVisitor.java | 5 ++ .../visitor/TeradataASTVisitorAdapter.java | 13 ++++ .../teradata/visitor/TeradataEvalVisitor.java | 73 +++++++++++++++++ .../visitor/TeradataOutputVisitor.java | 15 ++++ .../visitor/TeradataSchemaStatVisitor.java | 12 ++- .../sql/visitor/SQLEvalVisitorUtils.java | 5 ++ 9 files changed, 240 insertions(+), 5 deletions(-) create mode 100644 src/main/java/com/alibaba/druid/sql/dialect/teradata/ast/expr/TeradataIntervalExpr.java create mode 100644 src/main/java/com/alibaba/druid/sql/dialect/teradata/ast/expr/TeradataIntervalUnit.java create mode 100644 src/main/java/com/alibaba/druid/sql/dialect/teradata/visitor/TeradataEvalVisitor.java diff --git a/src/main/java/com/alibaba/druid/sql/dialect/teradata/ast/expr/TeradataIntervalExpr.java b/src/main/java/com/alibaba/druid/sql/dialect/teradata/ast/expr/TeradataIntervalExpr.java new file mode 100644 index 0000000000..e1128cd704 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/teradata/ast/expr/TeradataIntervalExpr.java @@ -0,0 +1,78 @@ +package com.alibaba.druid.sql.dialect.teradata.ast.expr; + +import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.ast.SQLExprImpl; +import com.alibaba.druid.sql.dialect.teradata.visitor.TeradataASTVisitor; +import com.alibaba.druid.sql.visitor.SQLASTVisitor; + +public class TeradataIntervalExpr extends SQLExprImpl implements TeradataExpr { + + private SQLExpr value; + private TeradataIntervalUnit unit; + + public TeradataIntervalExpr() { + + } + + public SQLExpr getValue() { + return this.value; + } + + public void setValue(SQLExpr value) { + this.value = value; + } + + public TeradataIntervalUnit getUnit() { + return unit; + } + + public void setUnit(TeradataIntervalUnit unit) { + this.unit = unit; + } + + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + TeradataIntervalExpr other = (TeradataIntervalExpr) obj; + if (unit != other.unit) { + return false; + } + if (value == null) { + if (other.value != null) { + return false; + } + } else if (!value.equals(other.value)) { + return false; + } + return true; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((unit == null)? 0 : unit.hashCode()); + result = prime * result + ((value == null)? 0 : value.hashCode()); + return result; + } + + @Override + protected void accept0(SQLASTVisitor visitor) { + TeradataASTVisitor tdVisitor = (TeradataASTVisitor) visitor; + if (tdVisitor.visit(this)) { + acceptChild(visitor, this.value); + } + tdVisitor.endVisit(this); + } + + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/teradata/ast/expr/TeradataIntervalUnit.java b/src/main/java/com/alibaba/druid/sql/dialect/teradata/ast/expr/TeradataIntervalUnit.java new file mode 100644 index 0000000000..cec3f559a5 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/teradata/ast/expr/TeradataIntervalUnit.java @@ -0,0 +1,14 @@ +package com.alibaba.druid.sql.dialect.teradata.ast.expr; + +public enum TeradataIntervalUnit { + + YEAR, MONTH, DAY, + + HOUR, MINUTE, SECOND; + + public final String name_lcase; + + private TeradataIntervalUnit() { + this.name_lcase = name().toLowerCase(); + } +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/teradata/parser/TeradataExprParser.java b/src/main/java/com/alibaba/druid/sql/dialect/teradata/parser/TeradataExprParser.java index 4e938a1ac6..e111143145 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/teradata/parser/TeradataExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/teradata/parser/TeradataExprParser.java @@ -15,13 +15,10 @@ */ package com.alibaba.druid.sql.dialect.teradata.parser; -import java.util.List; - import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLKeep; -import com.alibaba.druid.sql.ast.SQLOrderBy; -import com.alibaba.druid.sql.ast.SQLStatement; import com.alibaba.druid.sql.ast.SQLKeep.DenseRank; +import com.alibaba.druid.sql.ast.SQLOrderBy; import com.alibaba.druid.sql.ast.expr.SQLAggregateExpr; import com.alibaba.druid.sql.ast.expr.SQLAggregateOption; import com.alibaba.druid.sql.ast.expr.SQLCastExpr; @@ -29,6 +26,8 @@ import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.expr.SQLQueryExpr; import com.alibaba.druid.sql.dialect.teradata.ast.expr.TeradataAnalytic; import com.alibaba.druid.sql.dialect.teradata.ast.expr.TeradataAnalyticWindowing; +import com.alibaba.druid.sql.dialect.teradata.ast.expr.TeradataIntervalExpr; +import com.alibaba.druid.sql.dialect.teradata.ast.expr.TeradataIntervalUnit; import com.alibaba.druid.sql.parser.Lexer; import com.alibaba.druid.sql.parser.ParserException; import com.alibaba.druid.sql.parser.SQLExprParser; @@ -258,4 +257,27 @@ public class TeradataExprParser extends SQLExprParser { return aggregateExpr; } + protected SQLExpr parseInterval() { + accept(Token.INTERVAL); + + if (lexer.token() == Token.LITERAL_CHARS) { + SQLExpr value = expr(); + + if (lexer.token() != Token.IDENTIFIER) { + throw new ParserException("Syntax error"); + } + + String unit = lexer.stringVal(); + lexer.nextToken(); + + TeradataIntervalExpr intervalExpr = new TeradataIntervalExpr(); + intervalExpr.setValue(value); + intervalExpr.setUnit(TeradataIntervalUnit.valueOf(unit.toUpperCase())); + + return intervalExpr; + } else { + throw new ParserException("TODO with other interval"); + } + } + } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/teradata/visitor/TeradataASTVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/teradata/visitor/TeradataASTVisitor.java index 46e9b2fbdb..34d49ffbed 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/teradata/visitor/TeradataASTVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/teradata/visitor/TeradataASTVisitor.java @@ -19,6 +19,7 @@ import com.alibaba.druid.sql.ast.statement.SQLSelect; import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; import com.alibaba.druid.sql.dialect.teradata.ast.expr.TeradataAnalytic; import com.alibaba.druid.sql.dialect.teradata.ast.expr.TeradataAnalyticWindowing; +import com.alibaba.druid.sql.dialect.teradata.ast.expr.TeradataIntervalExpr; import com.alibaba.druid.sql.visitor.SQLASTVisitor; public interface TeradataASTVisitor extends SQLASTVisitor { @@ -32,4 +33,8 @@ public interface TeradataASTVisitor extends SQLASTVisitor { boolean visit(SQLSelectQueryBlock x); boolean visit(SQLSelect x); + + boolean visit(TeradataIntervalExpr x); + + void endVisit(TeradataIntervalExpr x); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/teradata/visitor/TeradataASTVisitorAdapter.java b/src/main/java/com/alibaba/druid/sql/dialect/teradata/visitor/TeradataASTVisitorAdapter.java index d7380d2bea..d286c6ddc4 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/teradata/visitor/TeradataASTVisitorAdapter.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/teradata/visitor/TeradataASTVisitorAdapter.java @@ -17,6 +17,7 @@ package com.alibaba.druid.sql.dialect.teradata.visitor; import com.alibaba.druid.sql.dialect.teradata.ast.expr.TeradataAnalytic; import com.alibaba.druid.sql.dialect.teradata.ast.expr.TeradataAnalyticWindowing; +import com.alibaba.druid.sql.dialect.teradata.ast.expr.TeradataIntervalExpr; import com.alibaba.druid.sql.visitor.SQLASTVisitorAdapter; public class TeradataASTVisitorAdapter extends SQLASTVisitorAdapter implements TeradataASTVisitor { @@ -39,4 +40,16 @@ public class TeradataASTVisitorAdapter extends SQLASTVisitorAdapter implements T return false; } + @Override + public boolean visit(TeradataIntervalExpr x) { + // TODO Auto-generated method stub + return true; + } + + @Override + public void endVisit(TeradataIntervalExpr x) { + // TODO Auto-generated method stub + + } + } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/teradata/visitor/TeradataEvalVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/teradata/visitor/TeradataEvalVisitor.java new file mode 100644 index 0000000000..14e482d1d8 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/teradata/visitor/TeradataEvalVisitor.java @@ -0,0 +1,73 @@ +package com.alibaba.druid.sql.dialect.teradata.visitor; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr; +import com.alibaba.druid.sql.visitor.SQLEvalVisitor; +import com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils; +import com.alibaba.druid.sql.visitor.functions.Function; + +public class TeradataEvalVisitor extends TeradataASTVisitorAdapter implements SQLEvalVisitor { + private Map functions = new HashMap(); + private List parameters = new ArrayList(); + + private int variantIndex = -1; + + private boolean markVariantIndex = true; + + public TeradataEvalVisitor() { + this(new ArrayList(1)); + } + + public TeradataEvalVisitor(List parameters) { + this.parameters = parameters; + } + + @Override + public Function getFunction(String funcName) { + return functions.get(funcName); + } + + @Override + public void registerFunction(String funcName, Function function) { + functions.put(funcName, function); + } + + @Override + public void unregisterFunction(String funcName) { + functions.remove(funcName); + } + + @Override + public List getParameters() { + return parameters; + } + + @Override + public void setParameters(List parameters) { + this.parameters = parameters; + } + + @Override + public int incrementAndGetVariantIndex() { + return ++variantIndex; + } + + @Override + public boolean isMarkVariantIndex() { + return markVariantIndex; + } + + @Override + public void setMarkVariantIndex(boolean markVariantIndex) { + this.markVariantIndex = markVariantIndex; + } + + public boolean visit(SQLBinaryOpExpr x) { + return SQLEvalVisitorUtils.visit(this, x); + } + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/teradata/visitor/TeradataOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/teradata/visitor/TeradataOutputVisitor.java index 6960a77d60..f0bc9ab3dc 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/teradata/visitor/TeradataOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/teradata/visitor/TeradataOutputVisitor.java @@ -23,6 +23,7 @@ import com.alibaba.druid.sql.ast.statement.SQLSelect; import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; import com.alibaba.druid.sql.dialect.teradata.ast.expr.TeradataAnalytic; import com.alibaba.druid.sql.dialect.teradata.ast.expr.TeradataAnalyticWindowing; +import com.alibaba.druid.sql.dialect.teradata.ast.expr.TeradataIntervalExpr; import com.alibaba.druid.sql.dialect.teradata.ast.stmt.TeradataSelectQueryBlock; import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor; @@ -158,4 +159,18 @@ public class TeradataOutputVisitor extends SQLASTOutputVisitor implements Terada } } } + + @Override + public boolean visit(TeradataIntervalExpr x) { + print0(ucase ? "INTERVAL " : "interval "); + x.getValue().accept(this); + print(' '); + print0(ucase ? x.getUnit().name() : x.getUnit().name_lcase); + return false; + } + + @Override + public void endVisit(TeradataIntervalExpr x) { + + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/teradata/visitor/TeradataSchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/teradata/visitor/TeradataSchemaStatVisitor.java index 141732f44f..fffec46566 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/teradata/visitor/TeradataSchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/teradata/visitor/TeradataSchemaStatVisitor.java @@ -17,6 +17,7 @@ package com.alibaba.druid.sql.dialect.teradata.visitor; import com.alibaba.druid.sql.dialect.teradata.ast.expr.TeradataAnalytic; import com.alibaba.druid.sql.dialect.teradata.ast.expr.TeradataAnalyticWindowing; +import com.alibaba.druid.sql.dialect.teradata.ast.expr.TeradataIntervalExpr; import com.alibaba.druid.sql.visitor.SchemaStatVisitor; import com.alibaba.druid.util.JdbcUtils; @@ -29,7 +30,6 @@ public class TeradataSchemaStatVisitor extends SchemaStatVisitor implements Tera @Override public boolean visit(TeradataAnalyticWindowing x) { - // TODO Auto-generated method stub return true; } @@ -45,4 +45,14 @@ public class TeradataSchemaStatVisitor extends SchemaStatVisitor implements Tera return false; } + @Override + public boolean visit(TeradataIntervalExpr x) { + return true; + } + + @Override + public void endVisit(TeradataIntervalExpr x) { + + } + } diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLEvalVisitorUtils.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLEvalVisitorUtils.java index 835cf24593..03247f8ec0 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLEvalVisitorUtils.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLEvalVisitorUtils.java @@ -44,6 +44,7 @@ import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlEvalVisitorImpl; import com.alibaba.druid.sql.dialect.oracle.visitor.OracleEvalVisitor; import com.alibaba.druid.sql.dialect.postgresql.visitor.PGEvalVisitor; import com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerEvalVisitor; +import com.alibaba.druid.sql.dialect.teradata.visitor.TeradataEvalVisitor; import com.alibaba.druid.sql.visitor.functions.Ascii; import com.alibaba.druid.sql.visitor.functions.Bin; import com.alibaba.druid.sql.visitor.functions.BitLength; @@ -178,6 +179,10 @@ public class SQLEvalVisitorUtils { if (JdbcUtils.DB2.equals(dbType)) { return new DB2EvalVisitor(); } + + if (JdbcUtils.TERADATA.equals(dbType)) { + return new TeradataEvalVisitor(); + } return new SQLEvalVisitorImpl(); }