diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBinaryOperator.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBinaryOperator.java index 409d5cf853..51f931b432 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBinaryOperator.java +++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBinaryOperator.java @@ -28,6 +28,7 @@ public enum SQLBinaryOperator { Multiply("*", 60), Divide("/", 60), Modulus("%", 60), + Mod("MOD", 60), Add("+", 70), Subtract("-", 70), diff --git a/src/main/java/com/alibaba/druid/sql/dialect/teradata/ast/stmt/TeradataSelectQueryBlock.java b/src/main/java/com/alibaba/druid/sql/dialect/teradata/ast/stmt/TeradataSelectQueryBlock.java index cefebc2ea8..2296c9314c 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/teradata/ast/stmt/TeradataSelectQueryBlock.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/teradata/ast/stmt/TeradataSelectQueryBlock.java @@ -1,6 +1,7 @@ package com.alibaba.druid.sql.dialect.teradata.ast.stmt; import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLOrderBy; import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; import com.alibaba.druid.sql.dialect.teradata.visitor.TeradataASTVisitor; @@ -8,6 +9,7 @@ import com.alibaba.druid.sql.visitor.SQLASTVisitor; public class TeradataSelectQueryBlock extends SQLSelectQueryBlock { private SQLOrderBy orderBy; + private SQLExpr qualifyClause; public TeradataSelectQueryBlock() { @@ -30,6 +32,7 @@ public class TeradataSelectQueryBlock extends SQLSelectQueryBlock { acceptChild(visitor, this.from); acceptChild(visitor, this.where); acceptChild(visitor, this.groupBy); + acceptChild(visitor, this.qualifyClause); acceptChild(visitor, this.orderBy); } visitor.endVisit(this); @@ -43,6 +46,17 @@ public class TeradataSelectQueryBlock extends SQLSelectQueryBlock { this.orderBy = orderBy; } + public SQLExpr getQualifyClause() { + return qualifyClause; + } + + public void setQualifyClause(SQLExpr qualify) { + if (qualify != null) { + qualify.setParent(this); + } + this.qualifyClause = qualify; + } + public String toString() { return SQLUtils.toTeradataString(this); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/teradata/parser/TeradataLexer.java b/src/main/java/com/alibaba/druid/sql/dialect/teradata/parser/TeradataLexer.java index 42bbd60dc1..4defb47f59 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/teradata/parser/TeradataLexer.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/teradata/parser/TeradataLexer.java @@ -45,6 +45,10 @@ public class TeradataLexer extends Lexer { map.put("FORMAT", Token.FORMAT); + map.put("QUALIFY", Token.QUALIFY); + + map.put("MOD", Token.MOD); + DEFAULT_TD_KEYWORDS = new Keywords(map); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/teradata/parser/TeradataSelectParser.java b/src/main/java/com/alibaba/druid/sql/dialect/teradata/parser/TeradataSelectParser.java index bdd0fbd204..e5c166e2c5 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/teradata/parser/TeradataSelectParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/teradata/parser/TeradataSelectParser.java @@ -1,9 +1,17 @@ package com.alibaba.druid.sql.dialect.teradata.parser; +import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.ast.SQLName; import com.alibaba.druid.sql.ast.SQLSetQuantifier; +import com.alibaba.druid.sql.ast.expr.SQLAggregateExpr; +import com.alibaba.druid.sql.ast.expr.SQLDefaultExpr; +import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; +import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr; +import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; import com.alibaba.druid.sql.ast.statement.SQLSelectQuery; import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; import com.alibaba.druid.sql.dialect.teradata.ast.stmt.TeradataSelectQueryBlock; +import com.alibaba.druid.sql.parser.ParserException; import com.alibaba.druid.sql.parser.SQLExprParser; import com.alibaba.druid.sql.parser.SQLSelectParser; import com.alibaba.druid.sql.parser.Token; @@ -54,9 +62,49 @@ public class TeradataSelectParser extends SQLSelectParser{ parseGroupBy(queryBlock); + parserQualify(queryBlock); + queryBlock.setOrderBy(this.exprParser.parseOrderBy()); return queryRest(queryBlock); } + private void parserQualify(TeradataSelectQueryBlock queryBlock) { + if (lexer.token() != Token.QUALIFY) { + return; + } + + lexer.nextToken(); + if (lexer.token() == Token.LITERAL_INT) { + lexer.nextToken(); + // possibly =, >=, <= + // ignore this for now + lexer.nextToken(); + + if (lexer.token() == Token.IDENTIFIER) { + SQLExpr expr = new SQLIdentifierExpr(lexer.stringVal()); + lexer.nextToken(); + if (lexer.token() != Token.COMMA) { + expr = this.exprParser.primaryRest(expr); + } + // TODO: add qualify clause into queryBlock + queryBlock.setQualifyClause(expr); + } else { + throw new ParserException("not support token:" + lexer.token()); + } + } else if (lexer.token() == Token.IDENTIFIER) { + SQLExpr expr = new SQLIdentifierExpr(lexer.stringVal()); + lexer.nextToken(); + if (lexer.token() != Token.COMMA) { + expr = this.exprParser.primaryRest(expr); + } + lexer.nextToken(); + lexer.nextToken(); + // TODO: add qualify clause into queryBlock + queryBlock.setQualifyClause(expr); + } else { + throw new ParserException("not support token:" + lexer.token()); + } + } + } 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 059ef1187f..7dfd051f69 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/Token.java +++ b/src/main/java/com/alibaba/druid/sql/parser/Token.java @@ -272,6 +272,7 @@ public enum Token { RANGE_N("RANGE_N"), FORMAT("FORMAT"), QUALIFY("QUALIFY"), + MOD("MOD"), LPAREN("("), RPAREN(")"),