From 1ce92f7d43bc7a30be73a1cc29312f432fccc600 Mon Sep 17 00:00:00 2001 From: Louis Xu Date: Fri, 8 Apr 2016 10:40:11 +0800 Subject: [PATCH 1/9] Add support for TD subquery table source implementation --- .../teradata/visitor/TeradataASTVisitor.java | 5 ++++ .../visitor/TeradataSchemaStatVisitor.java | 30 +++++++++++++++++++ 2 files changed, 35 insertions(+) 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 34d49ffbed..3fb1d36b69 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 @@ -17,6 +17,7 @@ package com.alibaba.druid.sql.dialect.teradata.visitor; import com.alibaba.druid.sql.ast.statement.SQLSelect; import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; +import com.alibaba.druid.sql.ast.statement.SQLSubqueryTableSource; 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; @@ -37,4 +38,8 @@ public interface TeradataASTVisitor extends SQLASTVisitor { boolean visit(TeradataIntervalExpr x); void endVisit(TeradataIntervalExpr x); + + boolean visit(SQLSubqueryTableSource x); + + void endVisit(SQLSubqueryTableSource 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 fffec46566..7b90268d99 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 @@ -15,6 +15,10 @@ */ package com.alibaba.druid.sql.dialect.teradata.visitor; +import java.util.Map; + +import com.alibaba.druid.sql.ast.statement.SQLSelectQuery; +import com.alibaba.druid.sql.ast.statement.SQLSubqueryTableSource; 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; @@ -54,5 +58,31 @@ public class TeradataSchemaStatVisitor extends SchemaStatVisitor implements Tera public void endVisit(TeradataIntervalExpr x) { } + + @Override + public boolean visit(SQLSubqueryTableSource x) { + accept(x.getSelect()); + + String table = (String) x.getSelect().getAttribute(ATTR_TABLE); + if (aliasMap != null && x.getAlias() != null) { + if (table != null) { + this.aliasMap.put(x.getAlias(), table); + } + addSubQuery(x.getAlias(), x.getSelect()); + this.setCurrentTable(x.getAlias()); + } + + if (table != null) { + x.putAttribute(ATTR_TABLE, table); + } + + return false; + } + + @Override + public void endVisit(SQLSubqueryTableSource x) { + + } + } From 051910f66628ff4438c86ecdf5f6ea16810454f9 Mon Sep 17 00:00:00 2001 From: Louis Xu Date: Mon, 11 Apr 2016 17:26:17 +0800 Subject: [PATCH 2/9] [bug fix] Add support for TD insert...sel --- .../sql/dialect/teradata/parser/TeradataStatementParser.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/alibaba/druid/sql/dialect/teradata/parser/TeradataStatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/teradata/parser/TeradataStatementParser.java index 5ca482bcfd..5a8354e1c3 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/teradata/parser/TeradataStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/teradata/parser/TeradataStatementParser.java @@ -118,7 +118,8 @@ public class TeradataStatementParser extends SQLStatementParser { break; } - } else if (lexer.token() == (Token.SELECT)) { + } else if (lexer.token() == (Token.SELECT) + || lexer.token() == (Token.SEL)) { SQLSelect select = this.exprParser.createSelectParser().select(); select.setParent(insertStatement); insertStatement.setQuery(select); From 4f0745705136faa1bb073b88def8c373b1252f4b Mon Sep 17 00:00:00 2001 From: Louis Xu Date: Tue, 12 Apr 2016 22:37:01 +0800 Subject: [PATCH 3/9] Add AggregateExpr and MethodInvokeExpr into aliasMap for TD --- .../visitor/TeradataSchemaStatVisitor.java | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) 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 7b90268d99..79f54d6438 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,12 +17,17 @@ package com.alibaba.druid.sql.dialect.teradata.visitor; import java.util.Map; +import com.alibaba.druid.sql.ast.SQLName; +import com.alibaba.druid.sql.ast.expr.SQLAggregateExpr; +import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr; +import com.alibaba.druid.sql.ast.statement.SQLSelectItem; import com.alibaba.druid.sql.ast.statement.SQLSelectQuery; import com.alibaba.druid.sql.ast.statement.SQLSubqueryTableSource; 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.stat.TableStat.Column; import com.alibaba.druid.util.JdbcUtils; public class TeradataSchemaStatVisitor extends SchemaStatVisitor implements TeradataASTVisitor { @@ -84,5 +89,34 @@ public class TeradataSchemaStatVisitor extends SchemaStatVisitor implements Tera } + public boolean visit(SQLSelectItem x) { + x.getExpr().accept(this); + + String alias = x.getAlias(); + + Map aliasMap = this.getAliasMap(); + if (alias != null && (!alias.isEmpty()) && aliasMap != null) { + if (x.getExpr() instanceof SQLName) { + putAliasMap(aliasMap, alias, x.getExpr().toString()); + } else if (x.getExpr() instanceof SQLAggregateExpr + || x.getExpr() instanceof SQLMethodInvokeExpr) { + TeradataSchemaStatVisitor visitor = new TeradataSchemaStatVisitor(); + x.getExpr().accept(visitor); + for (Column col : visitor.getColumns()) { + if (col.getTable().equalsIgnoreCase("unknown") + || this.getCurrentTable() != null) { + col.setTable(this.currentTable); + } + putAliasMap(aliasMap, alias, col.toString()); + } + } + else { + putAliasMap(aliasMap, alias, null); + } + } + + return false; + } + } From a5bec007f4efe802cc8e45a8fc7809381253724d Mon Sep 17 00:00:00 2001 From: Louis Xu Date: Wed, 13 Apr 2016 19:58:51 +0800 Subject: [PATCH 4/9] Add support for TD 'SEL' as SQLSubqueryTableSource rather than SQLExprTableSource --- .../java/com/alibaba/druid/sql/parser/SQLSelectParser.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 ae8703e8bc..7a9031e8bd 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java @@ -382,7 +382,8 @@ public class SQLSelectParser extends SQLParser { if (lexer.token() == Token.LPAREN) { lexer.nextToken(); SQLTableSource tableSource; - if (lexer.token() == Token.SELECT || lexer.token() == Token.WITH) { + if (lexer.token() == Token.SELECT || lexer.token() == Token.WITH + || lexer.token == Token.SEL) { SQLSelect select = select(); accept(Token.RPAREN); SQLSelectQuery query = queryRest(select.getQuery()); From 1091861bb15876131653191ae409a523aa8ec0c5 Mon Sep 17 00:00:00 2001 From: Louis Xu Date: Fri, 15 Apr 2016 18:21:13 +0800 Subject: [PATCH 5/9] [bug fix] keep column name unchanged if aliasMap value is null --- .../com/alibaba/druid/sql/visitor/SchemaStatVisitor.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) 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 9839bf9bc7..54dc56d25a 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java @@ -760,12 +760,14 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { Map aliasMap = getAliasMap(); if (aliasMap != null) { - if (aliasMap.containsKey(name)) { + if (aliasMap.containsKey(name) + && aliasMap.get(name) != null) { return aliasMap.get(name); } String name_lcase = name.toLowerCase(); - if (name_lcase != name && aliasMap.containsKey(name_lcase)) { + if (name_lcase != name && aliasMap.containsKey(name_lcase) + && aliasMap.get(name_lcase) != null) { return aliasMap.get(name_lcase); } From a347bdc435cad9567e937642188e949d7a1128e7 Mon Sep 17 00:00:00 2001 From: Louis Xu Date: Wed, 20 Apr 2016 18:34:05 +0800 Subject: [PATCH 6/9] Add support for TD QUALIFY keyword --- src/main/java/com/alibaba/druid/sql/parser/Token.java | 1 + 1 file changed, 1 insertion(+) 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 7f5dd6f188..059ef1187f 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/Token.java +++ b/src/main/java/com/alibaba/druid/sql/parser/Token.java @@ -271,6 +271,7 @@ public enum Token { POSITION("POSITION"), RANGE_N("RANGE_N"), FORMAT("FORMAT"), + QUALIFY("QUALIFY"), LPAREN("("), RPAREN(")"), From 5e1f16592dc7923b18df24a0ba08d7eaa90dba86 Mon Sep 17 00:00:00 2001 From: Louis Xu Date: Thu, 21 Apr 2016 17:20:53 +0800 Subject: [PATCH 7/9] Add support for Teradata 'MOD' and 'QUALIFY' keyword --- .../druid/sql/ast/expr/SQLBinaryOperator.java | 1 + .../ast/stmt/TeradataSelectQueryBlock.java | 14 ++++++ .../teradata/parser/TeradataLexer.java | 4 ++ .../teradata/parser/TeradataSelectParser.java | 48 +++++++++++++++++++ .../com/alibaba/druid/sql/parser/Token.java | 1 + 5 files changed, 68 insertions(+) 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(")"), From 098f603280a7548310c0b71ae74990b72dc03738 Mon Sep 17 00:00:00 2001 From: Louis Xu Date: Thu, 21 Apr 2016 17:22:43 +0800 Subject: [PATCH 8/9] Add Mod operation as SQLBinaryOpExpr --- .../teradata/parser/TeradataExprParser.java | 41 ++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) 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 93ca424523..56e44bdeb1 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 @@ -21,6 +21,10 @@ 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.SQLBetweenExpr; +import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr; +import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator; +import com.alibaba.druid.sql.ast.expr.SQLCaseExpr; import com.alibaba.druid.sql.ast.expr.SQLCastExpr; import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr; @@ -63,7 +67,6 @@ public class TeradataExprParser extends SQLExprParser { sqlExpr = queryExpr; return primaryRest(sqlExpr); case CAST: - System.out.println("cast test!"); lexer.nextToken(); accept(Token.LPAREN); SQLCastExpr cast = new SQLCastExpr(); @@ -87,6 +90,27 @@ public class TeradataExprParser extends SQLExprParser { return new TeradataSelectParser(this); } + // for cases like: between DATE '2010-01-01' and DATE '2011-01-01' + public SQLExpr relationalRest(SQLExpr expr) { + if (lexer.token() == Token.BETWEEN) { + lexer.nextToken(); + SQLExpr beginExpr = bitOr(); + SQLExpr endExpr; + if (lexer.token() != Token.AND) { + lexer.nextToken(); + accept(Token.AND); + endExpr = bitOr(); + lexer.nextToken(); + } else { + accept(Token.AND); + endExpr = bitOr(); + } + expr = new SQLBetweenExpr(expr, beginExpr, endExpr); + return expr; + } + return super.relationalRest(expr); + } + protected SQLExpr methodRest(SQLExpr expr, boolean acceptLPAREN) { if (acceptLPAREN) { accept(Token.LPAREN); @@ -121,10 +145,25 @@ public class TeradataExprParser extends SQLExprParser { accept(Token.RPAREN); return primaryRest(methodExpr); } + } else if (expr instanceof SQLCaseExpr) { + lexer.nextToken(); + accept(Token.RPAREN); + return primaryRest(expr); } return super.methodRest(expr, false); } + public SQLExpr multiplicativeRest(SQLExpr expr) { + if (lexer.token() == Token.MOD) { + lexer.nextToken(); + SQLExpr rightExp = bitXor(); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Mod, rightExp, getDbType()); + expr = multiplicativeRest(expr); + return expr; + } + return super.multiplicativeRest(expr); + } + protected SQLAggregateExpr parseAggregateExpr(String methodName) { methodName = methodName.toUpperCase(); From 48cf09635b0994ed63ba902228156e48de22e460 Mon Sep 17 00:00:00 2001 From: Louis Xu Date: Thu, 21 Apr 2016 17:24:22 +0800 Subject: [PATCH 9/9] create aliasQueryMap to store alias->expression, in case null returned in alias map --- .../visitor/TeradataSchemaStatVisitor.java | 38 +++++++++++++------ 1 file changed, 26 insertions(+), 12 deletions(-) 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 79f54d6438..706eb38799 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 @@ -15,10 +15,13 @@ */ package com.alibaba.druid.sql.dialect.teradata.visitor; +import java.util.LinkedHashMap; import java.util.Map; import com.alibaba.druid.sql.ast.SQLName; +import com.alibaba.druid.sql.ast.SQLObject; import com.alibaba.druid.sql.ast.expr.SQLAggregateExpr; +import com.alibaba.druid.sql.ast.expr.SQLCaseExpr; import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr; import com.alibaba.druid.sql.ast.statement.SQLSelectItem; import com.alibaba.druid.sql.ast.statement.SQLSelectQuery; @@ -32,6 +35,8 @@ import com.alibaba.druid.util.JdbcUtils; public class TeradataSchemaStatVisitor extends SchemaStatVisitor implements TeradataASTVisitor { + protected final Map aliasQueryMap = new LinkedHashMap(); + @Override public String getDbType() { return JdbcUtils.TERADATA; @@ -98,25 +103,34 @@ public class TeradataSchemaStatVisitor extends SchemaStatVisitor implements Tera if (alias != null && (!alias.isEmpty()) && aliasMap != null) { if (x.getExpr() instanceof SQLName) { putAliasMap(aliasMap, alias, x.getExpr().toString()); - } else if (x.getExpr() instanceof SQLAggregateExpr - || x.getExpr() instanceof SQLMethodInvokeExpr) { + } else { TeradataSchemaStatVisitor visitor = new TeradataSchemaStatVisitor(); x.getExpr().accept(visitor); - for (Column col : visitor.getColumns()) { - if (col.getTable().equalsIgnoreCase("unknown") - || this.getCurrentTable() != null) { - col.setTable(this.currentTable); - } - putAliasMap(aliasMap, alias, col.toString()); - } - } - else { - putAliasMap(aliasMap, alias, null); + putAliasMap(aliasMap, alias, null); + // Add expression alias into aliasQuery map + // in order to retrieve column info from aliasQueryMap + // if aliasMap value is null + String uniqueAliasName = this.getCurrentTable() == null ? + alias : this.getCurrentTable() + "." + alias; + addAliasQuery(uniqueAliasName, x.getExpr()); } } return false; } + protected void addAliasQuery(String alias, SQLObject query) { + String alias_lcase = alias.toLowerCase(); + aliasQueryMap.put(alias_lcase, query); + } + + public SQLObject getAliasQuery(String alias) { + String alias_lcase = alias.toLowerCase(); + return aliasQueryMap.get(alias_lcase); + } + + public Map getAliasQueryMap() { + return aliasQueryMap; + } }