http://git-wip-us.apache.org/repos/asf/tajo/blob/1b3ec373/tajo-core/src/main/java/org/apache/tajo/engine/parser/HiveQLAnalyzer.java ---------------------------------------------------------------------- diff --cc tajo-core/src/main/java/org/apache/tajo/engine/parser/HiveQLAnalyzer.java index 0000000,60e9685..f462db9 mode 000000,100644..100644 --- a/tajo-core/src/main/java/org/apache/tajo/engine/parser/HiveQLAnalyzer.java +++ b/tajo-core/src/main/java/org/apache/tajo/engine/parser/HiveQLAnalyzer.java @@@ -1,0 -1,1550 +1,1550 @@@ + /** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.tajo.engine.parser; + + import org.antlr.v4.runtime.ANTLRInputStream; + import org.antlr.v4.runtime.CharStream; + import org.antlr.v4.runtime.CommonTokenStream; + import org.antlr.v4.runtime.tree.TerminalNodeImpl; + import org.apache.commons.lang.math.NumberUtils; + import org.apache.commons.logging.Log; + import org.apache.commons.logging.LogFactory; + import org.apache.tajo.algebra.*; + import org.apache.tajo.common.TajoDataTypes; + import org.apache.tajo.engine.parser.HiveQLParser.TableAllColumnsContext; + + import java.math.BigInteger; + import java.util.*; + + public class HiveQLAnalyzer extends HiveQLParserBaseVisitor<Expr> { + private static final Log LOG = LogFactory.getLog(HiveQLAnalyzer.class.getName()); + private HiveQLParser parser; + + public Expr parse(String sql) { + HiveQLLexer lexer = new HiveQLLexer(new ANTLRNoCaseStringStream(sql)); + CommonTokenStream tokens = new CommonTokenStream(lexer); + parser = new HiveQLParser(tokens); + parser.setBuildParseTree(true); + + HiveQLParser.StatementContext context; + try { + context = parser.statement(); + } catch (SQLParseError e) { + throw new SQLSyntaxError(e); + } + + return visit(context); + } + + @Override + public Expr visitStatement(HiveQLParser.StatementContext ctx) { + return visitExecStatement(ctx.execStatement()); + } + + @Override + public Expr visitQueryStatement(HiveQLParser.QueryStatementContext ctx) { + Expr current = null; + + if (ctx.body != null) { + current = visitBody(ctx.body(0)); + } + + if (ctx.regular_body() != null) { + current = visitRegular_body(ctx.regular_body()); + } + + return current; + } + + @Override + public Expr visitBody(HiveQLParser.BodyContext ctx) { + + Expr current = null; + Insert insert = null; + + Projection select = null; + + if (ctx.insertClause() != null) { + insert = visitInsertClause(ctx.insertClause()); + } + + if (ctx.selectClause() != null) { + select = (Projection) visitSelectClause(ctx.selectClause()); + if (ctx.selectClause().KW_DISTINCT() != null) { + select.setDistinct(); + } + + } + + for (int i = 0; i < ctx.getParent().getChildCount(); i++) { + if (ctx.getParent().getChild(i) instanceof HiveQLParser.FromClauseContext) { + HiveQLParser.FromClauseContext fromClauseContext = (HiveQLParser.FromClauseContext) ctx.getParent().getChild(i); + Expr from = visitFromClause(fromClauseContext); + current = from; + } + } + + if (ctx.whereClause() != null) { + Selection where = new Selection(visitWhereClause(ctx.whereClause())); + where.setChild(current); + current = where; + } + + if (ctx.groupByClause() != null) { + Aggregation aggregation = visitGroupByClause(ctx.groupByClause()); + aggregation.setChild(current); + current = aggregation; + + if (ctx.havingClause() != null) { + Expr havingCondition = visitHavingClause(ctx.havingClause()); + Having having = new Having(havingCondition); + having.setChild(current); + current = having; + } + } + + if (ctx.orderByClause() != null) { + Sort sort = visitOrderByClause(ctx.orderByClause()); + sort.setChild(current); + current = sort; + } + + if (ctx.clusterByClause() != null) { + visitClusterByClause(ctx.clusterByClause()); + } + + if (ctx.distributeByClause() != null) { + visitDistributeByClause(ctx.distributeByClause()); + } + + if (ctx.sortByClause() != null) { + Sort sort = visitSortByClause(ctx.sortByClause()); + sort.setChild(current); + current = sort; + } + + if (ctx.window_clause() != null) { + Expr window = visitWindow_clause(ctx.window_clause()); + } + + if (ctx.limitClause() != null) { + Limit limit = visitLimitClause(ctx.limitClause()); + limit.setChild(current); + current = limit; + } + + Projection projection = new Projection(); + projection.setNamedExprs(select.getNamedExprs()); + + if (current != null) + projection.setChild(current); + + if (select.isDistinct()) + projection.setDistinct(); + + + if (insert != null) { + insert.setSubQuery(projection); + current = insert; + } else { + current = projection; + } + + return current; + } + + @Override + public Expr visitRegular_body(HiveQLParser.Regular_bodyContext ctx) { + Expr current = null; + Insert insert = null; + + if (ctx.selectStatement() != null) { + current = visitSelectStatement(ctx.selectStatement()); + } else { + Projection select = null; + + if (ctx.insertClause() != null) { + insert = visitInsertClause(ctx.insertClause()); + } + + if (ctx.selectClause() != null) { + select = (Projection) visitSelectClause(ctx.selectClause()); + if (ctx.selectClause().KW_DISTINCT() != null) { + select.setDistinct(); + } + + } + + if (ctx.fromClause() != null) { + Expr from = visitFromClause(ctx.fromClause()); + current = from; + } + + if (ctx.whereClause() != null) { + Selection where = new Selection(visitWhereClause(ctx.whereClause())); + where.setChild(current); + current = where; + } + + if (ctx.groupByClause() != null) { + Aggregation aggregation = visitGroupByClause(ctx.groupByClause()); + aggregation.setChild(current); + current = aggregation; + + if (ctx.havingClause() != null) { + Expr havingCondition = visitHavingClause(ctx.havingClause()); + Having having = new Having(havingCondition); + having.setChild(current); + current = having; + } + } + + if (ctx.orderByClause() != null) { + Sort sort = visitOrderByClause(ctx.orderByClause()); + sort.setChild(current); + current = sort; + } + + if (ctx.clusterByClause() != null) { + visitClusterByClause(ctx.clusterByClause()); + } + + if (ctx.distributeByClause() != null) { + visitDistributeByClause(ctx.distributeByClause()); + } + + if (ctx.sortByClause() != null) { + Sort sort = visitSortByClause(ctx.sortByClause()); + sort.setChild(current); + current = sort; + } + + if (ctx.window_clause() != null) { + Expr window = visitWindow_clause(ctx.window_clause()); + } + + if (ctx.limitClause() != null) { + Limit limit = visitLimitClause(ctx.limitClause()); + limit.setChild(current); + current = limit; + } + + Projection projection = new Projection(); + projection.setNamedExprs(select.getNamedExprs()); + + if (current != null) + projection.setChild(current); + + if (select.isDistinct()) + projection.setDistinct(); + + if (insert != null) { + insert.setSubQuery(projection); + current = insert; + } else { + current = projection; + } + + + } + return current; + } + + /** + * This method implemented for parsing union all clause. + * + * @param ctx + * @return + */ + @Override + public Expr visitQueryStatementExpression(HiveQLParser.QueryStatementExpressionContext ctx) { + Expr left = null, right = null, current = null; + if (ctx.queryStatement() != null) { + if (ctx.queryStatement().size() == 1) + return visitQueryStatement(ctx.queryStatement(0)); + + for (int i = 0; i < ctx.queryStatement().size(); i++) { + if (i == 0) + current = visitQueryStatement(ctx.queryStatement(i)); + else + left = current; + + if (i > 0) { + right = visitQueryStatement(ctx.queryStatement(i)); + current = new SetOperation(OpType.Union, left, right, false); + } + } + } + return current; + } + + @Override + public Expr visitSelectStatement(HiveQLParser.SelectStatementContext ctx) { + Expr current = null; + + Projection select = (Projection) visitSelectClause(ctx.selectClause()); + + if (ctx.selectClause().KW_DISTINCT() != null) { + select.setDistinct(); + } + + Expr from = visitFromClause(ctx.fromClause()); + current = from; + + if (ctx.whereClause() != null) { + Selection where = new Selection(visitWhereClause(ctx.whereClause())); + where.setChild(current); + current = where; + } + + if (ctx.groupByClause() != null) { + Aggregation aggregation = visitGroupByClause(ctx.groupByClause()); + aggregation.setChild(current); + current = aggregation; + + if (ctx.havingClause() != null) { + Expr havingCondition = visitHavingClause(ctx.havingClause()); + Having having = new Having(havingCondition); + having.setChild(current); + current = having; + } + } + + if (ctx.orderByClause() != null) { + Sort sort = visitOrderByClause(ctx.orderByClause()); + sort.setChild(current); + current = sort; + } + + if (ctx.clusterByClause() != null) { + visitClusterByClause(ctx.clusterByClause()); + } + + if (ctx.distributeByClause() != null) { + visitDistributeByClause(ctx.distributeByClause()); + } + + if (ctx.sortByClause() != null) { + Sort sort = visitSortByClause(ctx.sortByClause()); + sort.setChild(current); + current = sort; + } + + if (ctx.window_clause() != null) { + Expr window = visitWindow_clause(ctx.window_clause()); + } + + if (ctx.limitClause() != null) { + Limit limit = visitLimitClause(ctx.limitClause()); + limit.setChild(current); + current = limit; + } + + Projection projection = new Projection(); + projection.setNamedExprs(select.getNamedExprs()); + + if (current != null) + projection.setChild(current); + + if (select.isDistinct()) + projection.setDistinct(); + + current = projection; + + return current; + } + + @Override + public Expr visitFromClause(HiveQLParser.FromClauseContext ctx) { + return visitJoinSource(ctx.joinSource()); + } + + @Override + public Expr visitJoinSource(HiveQLParser.JoinSourceContext ctx) { + Expr[] relations = null; + RelationList relationList = null; + + if (ctx.fromSource() != null) { + int fromCount = ctx.fromSource().size(); + int uniqueJoinCount = ctx.uniqueJoinSource().size(); + + relations = new Expr[1]; + + Join current = null, parent = null; + JoinType type = null; + Expr left = null, right = null, condition = null; + + + if (fromCount == 1) { + relations[0] = visitFromSource(ctx.fromSource(0)); + } else { + left = visitFromSource((HiveQLParser.FromSourceContext) ctx.getChild(0)); + + for (int i = 1; i < ctx.getChildCount(); i++) { + type = null; + right = null; + condition = null; + + if (ctx.getChild(i) instanceof HiveQLParser.JoinTokenContext) { + type = getJoinType((HiveQLParser.JoinTokenContext) ctx.getChild(i)); + if (i > 1) + left = parent; + + if (i + 1 < ctx.getChildCount() && ctx.getChild(i + 1) instanceof HiveQLParser.FromSourceContext) { + right = visitFromSource((HiveQLParser.FromSourceContext) ctx.getChild(i + 1)); + } + + if (i + 3 < ctx.getChildCount() && ctx.getChild(i + 3) instanceof HiveQLParser.ExpressionContext) { + condition = visitExpression((HiveQLParser.ExpressionContext) ctx.getChild(i + 3)); + } + + if (type != null) { + current = new Join(type); + current.setLeft(left); + current.setRight(right); + + if (condition != null) + current.setQual(condition); + + parent = current; + } + } + + } + relations[0] = current; + } + + //TODO: implement unique join. + relationList = new RelationList(relations); + } + + return relationList; + } + + public JoinType getJoinType(HiveQLParser.JoinTokenContext context) { + JoinType type = JoinType.INNER; + + if (context.KW_INNER() != null) { + type = JoinType.INNER; + } + + if (context.KW_LEFT() != null && context.KW_OUTER() != null) { + type = JoinType.LEFT_OUTER; + } + + if (context.KW_RIGHT() != null && context.KW_OUTER() != null) { + type = JoinType.RIGHT_OUTER; + } + + if (context.KW_CROSS() != null) { + type = JoinType.CROSS; + } + + if (context.KW_FULL() != null) { + type = JoinType.FULL_OUTER; + } + + if (context.KW_SEMI() != null) { + type = null; + } + return type; + } + + @Override + public Expr visitFromSource(HiveQLParser.FromSourceContext ctx) { + Expr current = null; + + if (ctx.Identifier() != null && ctx.LPAREN() != null) { + current = new LiteralValue(ctx.Identifier().getText(), LiteralValue.LiteralType.String); + } + + if (ctx.tableSource() != null) { + current = visitTableSource(ctx.tableSource()); + } + + if (ctx.subQuerySource() != null) { + current = visitSubQuerySource(ctx.subQuerySource()); + + String tableAlias = ""; + for (int i = 0; i < ctx.subQuerySource().getChildCount(); i++) { + if (ctx.subQuerySource().getChild(i) instanceof HiveQLParser.IdentifierContext) { + tableAlias = (ctx.subQuerySource().getChild(i)).getText(); + } + } + + TablePrimarySubQuery subQuery = new TablePrimarySubQuery(tableAlias, current); + current = subQuery; + } + // TODO: implement lateralView + + return current; + } + + @Override + public Expr visitSubQuerySource(HiveQLParser.SubQuerySourceContext ctx) { + Expr current = visitQueryStatementExpression(ctx.queryStatementExpression()); + return current; + } + + @Override + public Expr visitTableSource(HiveQLParser.TableSourceContext ctx) { + String tableName = "", alias = ""; + + if (ctx.tableName() != null) + tableName = ctx.tableName().getText(); + + if (ctx.alias != null) { + alias = ctx.alias.getText(); + for (String token : HiveQLParser.tokenNames) { + if (token.replaceAll("'", "").equalsIgnoreCase(alias)) + alias = ""; + } + } + + Relation relation = new Relation(tableName); + if (!alias.equals("")) + relation.setAlias(alias); + + return relation; + } + + @Override + public Expr visitSelectList(HiveQLParser.SelectListContext ctx) { + Expr current = null; + Projection projection = new Projection(); + NamedExpr[] targets = new NamedExpr[ctx.selectItem().size()]; + for (int i = 0; i < targets.length; i++) { + targets[i] = visitSelectItem(ctx.selectItem(i)); + } + + projection.setNamedExprs(targets); + current = projection; + return current; + } + + @Override + public NamedExpr visitSelectItem(HiveQLParser.SelectItemContext ctx) { + NamedExpr target = null; + + if (ctx.selectExpression() != null) { + target = new NamedExpr(visitSelectExpression(ctx.selectExpression())); + } else if (ctx.window_specification() != null) { + // TODO: if there is a window specification clause, we should handle it properly. + } + + if (ctx.identifier().size() > 0 && target != null) { + target.setAlias(ctx.identifier(0).getText()); + } + return target; + } + + @Override + public Expr visitSelectExpression(HiveQLParser.SelectExpressionContext ctx) { + Expr current = null; + + if (ctx.tableAllColumns() != null) { + current = visitTableAllColumns(ctx.tableAllColumns()); + } else { + if (ctx.expression() != null) { + current = visitExpression(ctx.expression()); + } + } + + return current; + } + + @Override + public Expr visitTableAllColumns(TableAllColumnsContext ctx) { + QualifiedAsteriskExpr target = new QualifiedAsteriskExpr(); + if (ctx.tableName() != null) { + target.setQualifier(ctx.tableName().getText()); + } + + return target; + } + + @Override + public Expr visitExpression(HiveQLParser.ExpressionContext ctx) { + Expr current = visitPrecedenceOrExpression(ctx.precedenceOrExpression()); + return current; + } + + @Override + public Expr visitPrecedenceOrExpression(HiveQLParser.PrecedenceOrExpressionContext ctx) { + Expr current = null, left = null, right = null; + + for (int i = 0; i < ctx.precedenceAndExpression().size(); i++) { + if (i == 0) { + left = visitPrecedenceAndExpression(ctx.precedenceAndExpression(i)); + current = left; + } else { + left = current; + right = visitPrecedenceAndExpression(ctx.precedenceAndExpression(i)); + current = new BinaryOperator(OpType.Or, left, right); + } + + } + return current; + } + + /** + * This method parse AND expressions at WHERE clause. + * And this convert 'x BETWEEN y AND z' expression into 'x >= y AND x <= z' expression + * because Tajo doesn't provide 'BETWEEN' expression. + * + * @param ctx + * @return + */ + @Override + public Expr visitPrecedenceAndExpression(HiveQLParser.PrecedenceAndExpressionContext ctx) { + Expr current = null, left = null, right = null; + + for (int i = 0; i < ctx.precedenceNotExpression().size(); i++) { + Expr min = null, max = null; + + if (ctx.precedenceNotExpression(i).precedenceEqualExpression() != null) { + HiveQLParser.PrecedenceEqualExpressionContext expressionContext = ctx.precedenceNotExpression(i) + .precedenceEqualExpression(); + if (expressionContext.KW_BETWEEN() != null) { + + if (expressionContext.min != null) { + min = visitPrecedenceBitwiseOrExpression(expressionContext.min); + } + + if (expressionContext.max != null) { + max = visitPrecedenceBitwiseOrExpression(expressionContext.max); + } + } + } + + if (min != null && max != null) { + left = visitPrecedenceNotExpression(ctx.precedenceNotExpression(i)); + if (left != null) { + if (i == 0) { + BinaryOperator minOperator = new BinaryOperator(OpType.GreaterThanOrEquals, left, min); + BinaryOperator maxOperator = new BinaryOperator(OpType.LessThanOrEquals, left, max); + current = new BinaryOperator(OpType.And, minOperator, maxOperator); + } else { + BinaryOperator minOperator = new BinaryOperator(OpType.GreaterThanOrEquals, left, min); + current = new BinaryOperator(OpType.And, current, minOperator); + + BinaryOperator maxOperator = new BinaryOperator(OpType.LessThanOrEquals, left, max); + current = new BinaryOperator(OpType.And, current, maxOperator); + } + } + } else { + if (i == 0) { + left = visitPrecedenceNotExpression(ctx.precedenceNotExpression(i)); + current = left; + } else { + left = current; + right = visitPrecedenceNotExpression(ctx.precedenceNotExpression(i)); + current = new BinaryOperator(OpType.And, left, right); + } + } + } + return current; + } + + @Override + public Expr visitPrecedenceNotExpression(HiveQLParser.PrecedenceNotExpressionContext ctx) { + HiveQLParser.PrecedenceEqualExpressionContext expressionContext = ctx.precedenceEqualExpression(); + Expr current = visitPrecedenceEqualExpression(expressionContext); + return current; + } + + /** + * This method parse operators for equals expressions as follows: + * =, <>, !=, >=, >, <=, <, IN, NOT IN, LIKE, REGEXP, RLIKE + * <p/> + * In this case, this make RuntimeException> + * + * @param ctx + * @return + */ + @Override + public Expr visitPrecedenceEqualExpression(HiveQLParser.PrecedenceEqualExpressionContext ctx) { + Expr current = null, left = null, right = null, min = null, max = null; + OpType type = null; + boolean isNot = false, isIn = false; + for (int i = 0; i < ctx.getChildCount(); i++) { + if (ctx.getChild(i) instanceof HiveQLParser.PrecedenceBitwiseOrExpressionContext) { + if (i == 0) { + left = visitPrecedenceBitwiseOrExpression((HiveQLParser.PrecedenceBitwiseOrExpressionContext) ctx.getChild(i)); + } else { + right = visitPrecedenceBitwiseOrExpression((HiveQLParser.PrecedenceBitwiseOrExpressionContext) ctx.getChild(i)); + } + } else if (ctx.getChild(i) instanceof HiveQLParser.ExpressionsContext) { + right = visitExpressions((HiveQLParser.ExpressionsContext) ctx.getChild(i)); + } else if (ctx.getChild(i) instanceof TerminalNodeImpl) { + int symbolType = ((TerminalNodeImpl) ctx.getChild(i)).getSymbol().getType(); + switch (symbolType) { + case HiveQLLexer.KW_NOT: + isNot = true; + break; + case HiveQLLexer.KW_IN: + isIn = true; + break; + default: + break; + } + } else if (ctx.getChild(i) instanceof HiveQLParser.PrecedenceEqualOperatorContext + || ctx.getChild(i) instanceof HiveQLParser.PrecedenceEqualNegatableOperatorContext) { + String keyword = ctx.getChild(i).getText().toUpperCase(); + + if (keyword.equals(">")) { + type = OpType.GreaterThan; + } else if (keyword.equals("<=>")) { + throw new RuntimeException("Unexpected operator : <=>"); + } else if (keyword.equals("=")) { + type = OpType.Equals; + } else if (keyword.equals("<=")) { + type = OpType.LessThanOrEquals; + } else if (keyword.equals("<")) { + type = OpType.LessThan; + } else if (keyword.equals(">=")) { + type = OpType.GreaterThanOrEquals; + } else if (keyword.equals("<>")) { + type = OpType.NotEquals; + } else if (keyword.equals("!=")) { + type = OpType.NotEquals; + } else if (keyword.equals("REGEXP")) { + type = OpType.Regexp; + } else if (keyword.equals("RLIKE")) { + type = OpType.Regexp; + } else if (keyword.equals("LIKE")) { + type = OpType.LikePredicate; + } + } + } + + if (type != null && right != null) { + if (type.equals(OpType.LikePredicate)) { + PatternMatchPredicate like = new PatternMatchPredicate(OpType.LikePredicate, + isNot, left, right); + current = like; + } else if (type.equals(OpType.Regexp)) { + PatternMatchPredicate regex = new PatternMatchPredicate(OpType.Regexp, isNot, left, right); + current = regex; + } else { + BinaryOperator binaryOperator = new BinaryOperator(type, left, right); + current = binaryOperator; + } + } else if (isIn) { + InPredicate inPredicate = new InPredicate(left, right, isNot); + current = inPredicate; + } else { + current = left; + } + + return current; + } + + @Override + public ValueListExpr visitExpressions(HiveQLParser.ExpressionsContext ctx) { + int size = ctx.expression().size(); + Expr[] exprs = new Expr[size]; + for (int i = 0; i < size; i++) { + exprs[i] = visitExpression(ctx.expression(i)); + } + return new ValueListExpr(exprs); + } + + @Override + public Expr visitPrecedenceBitwiseOrExpression(HiveQLParser.PrecedenceBitwiseOrExpressionContext ctx) { + int expressionCount = ctx.precedenceAmpersandExpression().size(); + + Expr current = null, left = null, right = null, parentLeft, parentRight; + OpType type = null, parentType = null; + + for (int i = 0; i < expressionCount; i += 2) { + int operatorIndex = (i == 0) ? 0 : i - 1; + + if (ctx.precedenceBitwiseOrOperator(operatorIndex) != null) { + type = getPrecedenceBitwiseOrOperator(ctx.precedenceBitwiseOrOperator(operatorIndex)); + } + + if (i == 0) { + left = visitPrecedenceAmpersandExpression(ctx.precedenceAmpersandExpression(i)); + if (ctx.precedenceAmpersandExpression(i + 1) != null) + right = visitPrecedenceAmpersandExpression(ctx.precedenceAmpersandExpression(i + 1)); + } else { + parentType = getPrecedenceBitwiseOrOperator((ctx.precedenceBitwiseOrOperator(operatorIndex - 1))); + parentLeft = visitPrecedenceAmpersandExpression(ctx.precedenceAmpersandExpression(i - 2)); + parentRight = visitPrecedenceAmpersandExpression(ctx.precedenceAmpersandExpression(i - 1)); + left = new BinaryOperator(parentType, parentLeft, parentRight); + right = visitPrecedenceAmpersandExpression(ctx.precedenceAmpersandExpression(i)); + } + + if (right != null) { + current = new BinaryOperator(type, left, right); + } else { + current = left; + } + } + return current; + } + + public OpType getPrecedenceBitwiseOrOperator(HiveQLParser.PrecedenceBitwiseOrOperatorContext ctx) { + OpType type = null; + // TODO: It needs to consider how to support. + return type; + } + + @Override + public Expr visitPrecedenceAmpersandExpression(HiveQLParser.PrecedenceAmpersandExpressionContext ctx) { + int expressionCount = ctx.precedencePlusExpression().size(); + + Expr current = null, left = null, right = null, parentLeft, parentRight; + OpType type = null, parentType = null; + + for (int i = 0; i < expressionCount; i += 2) { + int operatorIndex = (i == 0) ? 0 : i - 1; + + if (ctx.precedenceAmpersandOperator(operatorIndex) != null) { + type = getPrecedenceAmpersandOperator(ctx.precedenceAmpersandOperator(operatorIndex)); + } + + if (i == 0) { + left = visitPrecedencePlusExpression(ctx.precedencePlusExpression(i)); + if (ctx.precedencePlusExpression(i + 1) != null) + right = visitPrecedencePlusExpression(ctx.precedencePlusExpression(i + 1)); + } else { + parentType = getPrecedenceAmpersandOperator((ctx.precedenceAmpersandOperator(operatorIndex - 1))); + parentLeft = visitPrecedencePlusExpression(ctx.precedencePlusExpression(i - 2)); + parentRight = visitPrecedencePlusExpression(ctx.precedencePlusExpression(i - 1)); + left = new BinaryOperator(parentType, parentLeft, parentRight); + right = visitPrecedencePlusExpression(ctx.precedencePlusExpression(i)); + } + + if (right != null) { + current = new BinaryOperator(type, left, right); + } else { + current = left; + } + } + return current; + } + + public OpType getPrecedenceAmpersandOperator(HiveQLParser.PrecedenceAmpersandOperatorContext ctx) { + OpType type = null; + // TODO: It needs to consider how to support. + return type; + } + + @Override + public Expr visitPrecedencePlusExpression(HiveQLParser.PrecedencePlusExpressionContext ctx) { + int expressionCount = ctx.precedenceStarExpression().size(); + + Expr current = null, left = null, right = null, parentLeft, parentRight; + OpType type = null, parentType = null; + + for (int i = 0; i < expressionCount; i += 2) { + int operatorIndex = (i == 0) ? 0 : i - 1; + + if (ctx.precedencePlusOperator(operatorIndex) != null) { + type = getPrecedencePlusOperator(ctx.precedencePlusOperator(operatorIndex)); + } + + if (i == 0) { + left = visitPrecedenceStarExpression(ctx.precedenceStarExpression(i)); + if (ctx.precedenceStarExpression(i + 1) != null) + right = visitPrecedenceStarExpression(ctx.precedenceStarExpression(i + 1)); + } else { + parentType = getPrecedencePlusOperator((ctx.precedencePlusOperator(operatorIndex - 1))); + parentLeft = visitPrecedenceStarExpression(ctx.precedenceStarExpression(i - 2)); + parentRight = visitPrecedenceStarExpression(ctx.precedenceStarExpression(i - 1)); + left = new BinaryOperator(parentType, parentLeft, parentRight); + right = visitPrecedenceStarExpression(ctx.precedenceStarExpression(i)); + } + + if (right != null) { + current = new BinaryOperator(type, left, right); + } else { + current = left; + } + } + return current; + } + + public OpType getPrecedencePlusOperator(HiveQLParser.PrecedencePlusOperatorContext ctx) { + OpType type = null; + + if (ctx.MINUS() != null) { + type = OpType.Minus; + } else if (ctx.PLUS() != null) { + type = OpType.Plus; + } + + return type; + } + + @Override + public Expr visitPrecedenceStarExpression(HiveQLParser.PrecedenceStarExpressionContext ctx) { + int expressionCount = ctx.precedenceBitwiseXorExpression().size(); + + Expr current = null, left = null, right = null, parentLeft, parentRight; + OpType type = null, parentType = null; + + for (int i = 0; i < expressionCount; i += 2) { + int operatorIndex = (i == 0) ? 0 : i - 1; + + if (ctx.precedenceStarOperator(operatorIndex) != null) { + type = getPrecedenceStarOperator(ctx.precedenceStarOperator(operatorIndex)); + } + + if (i == 0) { + left = visitPrecedenceBitwiseXorExpression(ctx.precedenceBitwiseXorExpression(i)); + if (ctx.precedenceBitwiseXorExpression(i + 1) != null) + right = visitPrecedenceBitwiseXorExpression(ctx.precedenceBitwiseXorExpression(i + 1)); + } else { + parentType = getPrecedenceStarOperator((ctx.precedenceStarOperator(operatorIndex - 1))); + parentLeft = visitPrecedenceBitwiseXorExpression(ctx.precedenceBitwiseXorExpression(i - 2)); + parentRight = visitPrecedenceBitwiseXorExpression(ctx.precedenceBitwiseXorExpression(i - 1)); + left = new BinaryOperator(parentType, parentLeft, parentRight); + right = visitPrecedenceBitwiseXorExpression(ctx.precedenceBitwiseXorExpression(i)); + } + + if (right != null) { + current = new BinaryOperator(type, left, right); + } else { + current = left; + } + } + + return current; + } + + public OpType getPrecedenceStarOperator(HiveQLParser.PrecedenceStarOperatorContext ctx) { + OpType type = null; + + if (ctx.DIV() != null) { + type = OpType.Divide; + } else if (ctx.DIVIDE() != null) { + type = OpType.Divide; + } else if (ctx.MOD() != null) { + type = OpType.Modular; + } else if (ctx.STAR() != null) { + type = OpType.Multiply; + } + + return type; + } + + @Override + public Expr visitPrecedenceBitwiseXorExpression(HiveQLParser.PrecedenceBitwiseXorExpressionContext ctx) { + int expressionCount = ctx.precedenceUnarySuffixExpression().size(); + + Expr current = null, left = null, right = null, parentLeft, parentRight; + OpType type = null, parentType = null; + + for (int i = 0; i < expressionCount; i += 2) { + int operatorIndex = (i == 0) ? 0 : i - 1; + + if (ctx.precedenceBitwiseXorOperator(operatorIndex) != null) { + type = getPrecedenceBitwiseXorOperator(ctx.precedenceBitwiseXorOperator(operatorIndex)); + } + + if (i == 0) { + left = visitPrecedenceUnarySuffixExpression(ctx.precedenceUnarySuffixExpression(i)); + if (ctx.precedenceUnarySuffixExpression(i + 1) != null) + right = visitPrecedenceUnarySuffixExpression(ctx.precedenceUnarySuffixExpression(i + 1)); + } else { + parentType = getPrecedenceBitwiseXorOperator((ctx.precedenceBitwiseXorOperator(operatorIndex - 1))); + parentLeft = visitPrecedenceUnarySuffixExpression(ctx.precedenceUnarySuffixExpression(i - 2)); + parentRight = visitPrecedenceUnarySuffixExpression(ctx.precedenceUnarySuffixExpression(i - 1)); + left = new BinaryOperator(parentType, parentLeft, parentRight); + right = visitPrecedenceUnarySuffixExpression(ctx.precedenceUnarySuffixExpression(i)); + } + + if (right != null) { + current = new BinaryOperator(type, left, right); + } else { + current = left; + } + } + + return current; + } + + public OpType getPrecedenceBitwiseXorOperator(HiveQLParser.PrecedenceBitwiseXorOperatorContext ctx) { + OpType type = null; + // TODO: It needs to consider how to support. + + return type; + } + + @Override + public Expr visitPrecedenceUnarySuffixExpression(HiveQLParser.PrecedenceUnarySuffixExpressionContext ctx) { + Expr current = visitPrecedenceUnaryPrefixExpression(ctx.precedenceUnaryPrefixExpression()); + + if (ctx.nullCondition() != null) { + boolean isNot = ctx.nullCondition().KW_NOT() == null ? false : true; + IsNullPredicate isNullPredicate = new IsNullPredicate(isNot, (ColumnReferenceExpr) current); + current = isNullPredicate; + } + + return current; + } + + @Override + public Expr visitPrecedenceUnaryPrefixExpression(HiveQLParser.PrecedenceUnaryPrefixExpressionContext ctx) { + Expr current = visitPrecedenceFieldExpression(ctx.precedenceFieldExpression()); + return current; + } + + @Override + public Expr visitNullCondition(HiveQLParser.NullConditionContext ctx) { + return new NullLiteral(); + } + + @Override + public Expr visitPrecedenceFieldExpression(HiveQLParser.PrecedenceFieldExpressionContext ctx) { + Expr current = visitAtomExpression(ctx.atomExpression()); + + if (ctx.DOT().size() > 0) { + ColumnReferenceExpr column = new ColumnReferenceExpr(ctx.identifier(0).getText()); + ColumnReferenceExpr table = (ColumnReferenceExpr) current; + column.setQualifier(table.getName()); + current = column; + } + return current; + } + + @Override + public Expr visitAtomExpression(HiveQLParser.AtomExpressionContext ctx) { + Expr current = null; + + if (ctx.KW_NULL() != null) { + current = new NullLiteral(); + } + if (ctx.constant() != null) { + current = visitConstant(ctx.constant()); + } + if (ctx.function() != null) { + current = visitFunction(ctx.function()); + } + if (ctx.castExpression() != null) { + current = visitCastExpression(ctx.castExpression()); + } + if (ctx.caseExpression() != null) { + current = visitCaseExpression(ctx.caseExpression()); + } + if (ctx.whenExpression() != null) { + current = visitWhenExpression(ctx.whenExpression()); + } + if (ctx.tableOrColumn() != null) { + current = visitTableOrColumn(ctx.tableOrColumn()); + } else { + if (ctx.LPAREN() != null && ctx.RPAREN() != null) { + current = visitExpression(ctx.expression()); + } + } + + return current; + } + + @Override + public Expr visitTableOrColumn(HiveQLParser.TableOrColumnContext ctx) { + ColumnReferenceExpr columnReferenceExpr = new ColumnReferenceExpr(ctx.identifier().getText()); + return columnReferenceExpr; + } + + @Override + public Expr visitIdentifier(HiveQLParser.IdentifierContext ctx) { + Expr current = null; + + if (ctx.nonReserved() != null) { + current = new LiteralValue(ctx.nonReserved().getText(), LiteralValue.LiteralType.String); + } else { + current = new LiteralValue(ctx.Identifier().getText(), LiteralValue.LiteralType.String); + } + + return current; + } + + @Override + public LiteralValue visitConstant(HiveQLParser.ConstantContext ctx) { + LiteralValue literalValue = null; + + if (ctx.StringLiteral() != null) { + String value = ctx.StringLiteral().getText(); + String strValue = ""; + if ((value.startsWith("'") && value.endsWith("'")) || value.startsWith("\"") && value.endsWith("\"")) { + strValue = value.substring(1, value.length() - 1); + } else { + strValue = value; + } + + literalValue = new LiteralValue(strValue, LiteralValue.LiteralType.String); + } else if (ctx.TinyintLiteral() != null) { + literalValue = new LiteralValue(ctx.TinyintLiteral().getSymbol().getText(), + LiteralValue.LiteralType.Unsigned_Integer); + } else if (ctx.BigintLiteral() != null) { + literalValue = new LiteralValue(ctx.BigintLiteral().getSymbol().getText(), + LiteralValue.LiteralType.Unsigned_Large_Integer); + } else if (ctx.DecimalLiteral() != null) { + literalValue = new LiteralValue(ctx.DecimalLiteral().getSymbol().getText(), + LiteralValue.LiteralType.Unsigned_Integer); + } else if (ctx.Number() != null) { + try { + float floatValue = NumberUtils.createFloat(ctx.getText()); + literalValue = new LiteralValue(ctx.Number().getSymbol().getText(), LiteralValue.LiteralType.Unsigned_Float); + } catch (NumberFormatException nf) { + } + + // TODO: double type + + try { + BigInteger bigIntegerVallue = NumberUtils.createBigInteger(ctx.getText()); + literalValue = new LiteralValue(ctx.Number().getSymbol().getText(), + LiteralValue.LiteralType.Unsigned_Large_Integer); + } catch (NumberFormatException nf) { + } + + try { + int intValue = NumberUtils.createInteger(ctx.getText()); + literalValue = new LiteralValue(ctx.Number().getSymbol().getText(), LiteralValue.LiteralType.Unsigned_Integer); + } catch (NumberFormatException nf) { + } + + } else if (ctx.SmallintLiteral() != null) { + literalValue = new LiteralValue(ctx.SmallintLiteral().getSymbol().getText(), + LiteralValue.LiteralType.Unsigned_Integer); + } else if (ctx.booleanValue() != null) { + // TODO: boolean type + } + + return literalValue; + } + + @Override + public Expr visitFunction(HiveQLParser.FunctionContext ctx) { + Expr current = null; + String signature = ctx.functionName().getText(); + + boolean isDistinct = false; + if (ctx.getChild(2) != null) { + if (ctx.getChild(2) instanceof TerminalNodeImpl && ctx.getChild(2).getText().equalsIgnoreCase("DISTINCT")) { + isDistinct = true; + } + } + + if (signature.equalsIgnoreCase("MIN") + || signature.equalsIgnoreCase("MAX") + || signature.equalsIgnoreCase("SUM") + || signature.equalsIgnoreCase("AVG") + || signature.equalsIgnoreCase("COUNT") + ) { + if (ctx.selectExpression().size() > 1) { + throw new RuntimeException("Exactly expected one argument."); + } + + if (ctx.selectExpression().size() == 0) { + CountRowsFunctionExpr countRowsFunctionExpr = new CountRowsFunctionExpr(); + current = countRowsFunctionExpr; + } else { - GeneralSetFunctionExpr setFunctionExpr = new GeneralSetFunctionExpr(signature, isDistinct, - visitSelectExpression(ctx.selectExpression(0))); ++ GeneralSetFunctionExpr setFunctionExpr = new GeneralSetFunctionExpr(signature, isDistinct, new Expr [] { ++ visitSelectExpression(ctx.selectExpression(0))}); + current = setFunctionExpr; + } + } else { + FunctionExpr functionExpr = new FunctionExpr(signature); + Expr[] params = new Expr[ctx.selectExpression().size()]; + for (int i = 0; i < ctx.selectExpression().size(); i++) { + params[i] = visitSelectExpression(ctx.selectExpression(i)); + } + functionExpr.setParams(params); + current = functionExpr; + } + + + return current; + } + + /** + * This method parse CAST expression. + * This returns only expression field without casting type + * because Tajo doesn't provide CAST expression. + * + * @param ctx + * @return + */ + @Override + public Expr visitCastExpression(HiveQLParser.CastExpressionContext ctx) { + DataTypeExpr castTarget = getDataTypeExpr(ctx.primitiveType()); + Expr expr = visitExpression(ctx.expression()); + Expr current = new CastExpr(expr, castTarget); + return current; + } + + @Override + public Expr visitCaseExpression(HiveQLParser.CaseExpressionContext ctx) { + CaseWhenPredicate caseWhen = new CaseWhenPredicate(); + Expr condition = null, result = null; + for (int i = 1; i < ctx.getChildCount(); i++) { + if (ctx.getChild(i) instanceof TerminalNodeImpl) { + if (((TerminalNodeImpl) ctx.getChild(i)).getSymbol().getType() == HiveQLLexer.KW_WHEN) { + condition = null; + result = null; + + if (ctx.getChild(i + 1) instanceof HiveQLParser.ExpressionContext) { + condition = visitExpression((HiveQLParser.ExpressionContext) ctx.getChild(i + 1)); + } + + if (ctx.getChild(i + 3) instanceof HiveQLParser.ExpressionContext) { + result = visitExpression((HiveQLParser.ExpressionContext) ctx.getChild(i + 3)); + } + + if (condition != null && result != null) { + caseWhen.addWhen(condition, result); + } + } else if (((TerminalNodeImpl) ctx.getChild(i)).getSymbol().getType() == HiveQLLexer.KW_ELSE) { + result = visitExpression((HiveQLParser.ExpressionContext) ctx.getChild(i + 1)); + caseWhen.setElseResult(result); + } + } + } + + return caseWhen; + } + + @Override + public Expr visitWhenExpression(HiveQLParser.WhenExpressionContext ctx) { + CaseWhenPredicate caseWhen = new CaseWhenPredicate(); + Expr condition = null, result = null; + for (int i = 1; i < ctx.getChildCount(); i++) { + if (ctx.getChild(i) instanceof TerminalNodeImpl) { + if (((TerminalNodeImpl) ctx.getChild(i)).getSymbol().getType() == HiveQLLexer.KW_WHEN) { + condition = null; + result = null; + + if (ctx.getChild(i + 1) instanceof HiveQLParser.ExpressionContext) { + condition = visitExpression((HiveQLParser.ExpressionContext) ctx.getChild(i + 1)); + } + + if (ctx.getChild(i + 3) instanceof HiveQLParser.ExpressionContext) { + result = visitExpression((HiveQLParser.ExpressionContext) ctx.getChild(i + 3)); + } + + if (condition != null && result != null) { + caseWhen.addWhen(condition, result); + } + } else if (((TerminalNodeImpl) ctx.getChild(i)).getSymbol().getType() == HiveQLLexer.KW_ELSE) { + result = visitExpression((HiveQLParser.ExpressionContext) ctx.getChild(i + 1)); + caseWhen.setElseResult(result); + } + } + } + + return caseWhen; + } + + @Override + public Aggregation visitGroupByClause(HiveQLParser.GroupByClauseContext ctx) { + Aggregation clause = new Aggregation(); + + if (ctx.groupByExpression().size() > 0) { + int elementSize = ctx.groupByExpression().size(); + ArrayList<Aggregation.GroupElement> groups = new ArrayList<Aggregation.GroupElement>(elementSize + 1); + ArrayList<Expr> ordinaryExprs = new ArrayList<Expr>(); + int groupSize = 1; + groups.add(null); + + for (int i = 0; i < ctx.groupByExpression().size(); i++) { + Expr expr = visitGroupByExpression(ctx.groupByExpression(i)); + + if (expr instanceof FunctionExpr) { + FunctionExpr function = (FunctionExpr) expr; + + if (function.getSignature().equalsIgnoreCase("ROLLUP")) { + groupSize++; + groups.add(new Aggregation.GroupElement(Aggregation.GroupType.Rollup, + function.getParams())); + } else if (function.getSignature().equalsIgnoreCase("CUBE")) { + groupSize++; + groups.add(new Aggregation.GroupElement(Aggregation.GroupType.Cube, function.getParams())); + } else { + Collections.addAll(ordinaryExprs, function); + } + } else { + Collections.addAll(ordinaryExprs, (ColumnReferenceExpr)expr); + } + } + + if (ordinaryExprs != null) { + groups.set(0, new Aggregation.GroupElement(Aggregation.GroupType.OrdinaryGroup, ordinaryExprs.toArray(new Expr[ordinaryExprs.size()]))); + clause.setGroups(groups.subList(0, groupSize).toArray(new Aggregation.GroupElement[groupSize])); + } else if (groupSize > 1) { + clause.setGroups(groups.subList(1, groupSize).toArray(new Aggregation.GroupElement[groupSize - 1])); + } + } + + //TODO: grouping set expression + return clause; + } + + @Override + public Sort visitOrderByClause(HiveQLParser.OrderByClauseContext ctx) { + Sort clause = null; + Sort.SortSpec[] specs = null; + + if (ctx.columnRefOrder().size() > 0) { + specs = new Sort.SortSpec[ctx.columnRefOrder().size()]; + for (int i = 0; i < ctx.columnRefOrder().size(); i++) { + ColumnReferenceExpr column = (ColumnReferenceExpr) visitExpression(ctx.columnRefOrder().get(i).expression()); + specs[i] = new Sort.SortSpec(column); + if (ctx.columnRefOrder(i).KW_DESC() != null) { + specs[i].setDescending(); + } + } + clause = new Sort(specs); + } + return clause; + + } + + @Override + public Expr visitHavingClause(HiveQLParser.HavingClauseContext ctx) { + return visitHavingCondition(ctx.havingCondition()); + } + + @Override + public Expr visitClusterByClause(HiveQLParser.ClusterByClauseContext ctx) { + // TODO: It needs to consider how to support. + return null; + } + + @Override + public Expr visitDistributeByClause(HiveQLParser.DistributeByClauseContext ctx) { + // TODO: It needs to consider how to support. + + return null; + } + + @Override + public Sort visitSortByClause(HiveQLParser.SortByClauseContext ctx) { + Sort clause = null; + Sort.SortSpec[] specs = null; + + if (ctx.columnRefOrder().size() > 0) { + specs = new Sort.SortSpec[ctx.columnRefOrder().size()]; + for (int i = 0; i < ctx.columnRefOrder().size(); i++) { + ColumnReferenceExpr column = (ColumnReferenceExpr) visitColumnRefOrder(ctx.columnRefOrder(i)); + specs[i] = new Sort.SortSpec(column); + + if (ctx.columnRefOrder(i).KW_DESC() != null) { + specs[i].setDescending(); + } + } + clause = new Sort(specs); + } + + return clause; + } + + @Override + public Limit visitLimitClause(HiveQLParser.LimitClauseContext ctx) { + LiteralValue expr = new LiteralValue(ctx.Number().getText(), LiteralValue.LiteralType.Unsigned_Integer); + Limit limit = new Limit(expr); + return limit; + } + + @Override + public Expr visitWindow_clause(HiveQLParser.Window_clauseContext ctx) { + // TODO: It needs to consider how to support. + return null; + } + + @Override + public Insert visitInsertClause(HiveQLParser.InsertClauseContext ctx) { + Insert insert = new Insert(); + if (ctx.KW_OVERWRITE() != null) + insert.setOverwrite(); + + if (ctx.tableOrPartition() != null) { + HiveQLParser.TableOrPartitionContext partitionContext = ctx.tableOrPartition(); + if (partitionContext.tableName() != null) { + insert.setTableName(ctx.tableOrPartition().tableName().getText()); + } + } + + if (ctx.destination() != null) { + HiveQLParser.DestinationContext destination = ctx.destination(); + if (destination.KW_DIRECTORY() != null) { + String location = destination.StringLiteral().getText(); + location = location.replaceAll("\\'", ""); + insert.setLocation(location); + } else if (destination.KW_TABLE() != null) { + if (destination.tableOrPartition() != null) { + HiveQLParser.TableOrPartitionContext partitionContext = destination.tableOrPartition(); + if (partitionContext.tableName() != null) { + insert.setTableName(partitionContext.tableName().getText()); + } + } + + if (destination.tableFileFormat() != null) { + if (destination.tableFileFormat().KW_RCFILE() != null) { + insert.setStorageType("rcfile"); + } else if (destination.tableFileFormat().KW_TEXTFILE() != null) { + insert.setStorageType("csv"); + } + + } + } + } + + return insert; + } + + @Override + public Expr visitCreateTableStatement(HiveQLParser.CreateTableStatementContext ctx) { + CreateTable createTable = null; + Map<String, String> params = new HashMap<String, String>(); + + if (ctx.name != null) { + createTable = new CreateTable(ctx.name.getText(), ctx.ifNotExists() != null); + if (ctx.KW_EXTERNAL() != null) { + createTable.setExternal(); + } + + if (ctx.tableFileFormat() != null) { + if (ctx.tableFileFormat().KW_RCFILE() != null) { + createTable.setStorageType("rcfile"); + } else if (ctx.tableFileFormat().KW_TEXTFILE() != null) { + createTable.setStorageType("csv"); + } + } + + if (ctx.tableRowFormat() != null) { + if (ctx.tableRowFormat().rowFormatDelimited() != null) { + String delimiter = ctx.tableRowFormat().rowFormatDelimited().tableRowFormatFieldIdentifier().getChild(3) + .getText().replaceAll("'", ""); + params.put("csvfile.delimiter", SQLAnalyzer.escapeDelimiter(delimiter)); + } + } + + if (ctx.tableLocation() != null) { + String location = ctx.tableLocation().StringLiteral().getText(); + location = location.replaceAll("'", ""); + createTable.setLocation(location); + + } + + if (ctx.columnNameTypeList() != null) { + List<HiveQLParser.ColumnNameTypeContext> list = ctx.columnNameTypeList().columnNameType(); + + ColumnDefinition[] columns = new ColumnDefinition[list.size()]; + + for (int i = 0; i < list.size(); i++) { + HiveQLParser.ColumnNameTypeContext eachColumn = list.get(i); + String type = null; + if (eachColumn.colType().type() != null) { + if (eachColumn.colType().type().primitiveType() != null) { + HiveQLParser.PrimitiveTypeContext primitiveType = eachColumn.colType().type().primitiveType(); + type = getDataTypeExpr(primitiveType).getTypeName(); + columns[i] = new ColumnDefinition(eachColumn.colName.Identifier().getText(), type); + } + } + } + if (columns != null) { + createTable.setTableElements(columns); + } + + if (!params.isEmpty()) { + createTable.setParams(params); + } + } + } + + return createTable; + } + + + private DataTypeExpr getDataTypeExpr(HiveQLParser.PrimitiveTypeContext primitiveType) { + DataTypeExpr typeDefinition = null; + + if (primitiveType.KW_STRING() != null) { + typeDefinition = new DataTypeExpr(TajoDataTypes.Type.TEXT.name()); + } else if (primitiveType.KW_TINYINT() != null) { + typeDefinition = new DataTypeExpr(TajoDataTypes.Type.INT1.name()); + } else if (primitiveType.KW_SMALLINT() != null) { + typeDefinition = new DataTypeExpr(TajoDataTypes.Type.INT2.name()); + } else if (primitiveType.KW_INT() != null) { + typeDefinition = new DataTypeExpr(TajoDataTypes.Type.INT4.name()); + } else if (primitiveType.KW_BIGINT() != null) { + typeDefinition = new DataTypeExpr(TajoDataTypes.Type.INT8.name()); + } else if (primitiveType.KW_FLOAT() != null) { + typeDefinition = new DataTypeExpr(TajoDataTypes.Type.FLOAT4.name()); + } else if (primitiveType.KW_DOUBLE() != null) { + typeDefinition = new DataTypeExpr(TajoDataTypes.Type.FLOAT8.name()); + } else if (primitiveType.KW_DECIMAL() != null) { + typeDefinition = new DataTypeExpr(TajoDataTypes.Type.NUMERIC.name()); + } else if (primitiveType.KW_BOOLEAN() != null) { + typeDefinition = new DataTypeExpr(TajoDataTypes.Type.BOOLEAN.name()); + } else if (primitiveType.KW_DATE() != null) { + } else if (primitiveType.KW_DATETIME() != null) { + //TODO + } else if (primitiveType.KW_TIMESTAMP() != null) { + typeDefinition = new DataTypeExpr(TajoDataTypes.Type.TIMESTAMP.name()); + } + + return typeDefinition; + } + + + @Override + public Expr visitDropTableStatement(HiveQLParser.DropTableStatementContext ctx) { + DropTable dropTable = new DropTable(ctx.tableName().getText(), false, ctx.ifExists() != null); + return dropTable; + } + + /** + * This class provides and implementation for a case insensitive token checker + * for the lexical analysis part of antlr. By converting the token stream into + * upper case at the time when lexical rules are checked, this class ensures that the + * lexical rules need to just match the token with upper case letters as opposed to + * combination of upper case and lower case characteres. This is purely used for matching lexical + * rules. The actual token text is stored in the same way as the user input without + * actually converting it into an upper case. The token values are generated by the consume() + * function of the super class ANTLRStringStream. The LA() function is the lookahead funtion + * and is purely used for matching lexical rules. This also means that the grammar will only + * accept capitalized tokens in case it is run from other tools like antlrworks which + * do not have the ANTLRNoCaseStringStream implementation. + */ + public class ANTLRNoCaseStringStream extends ANTLRInputStream { + + public ANTLRNoCaseStringStream(String input) { + super(input); + } + + @Override + public int LA(int i) { + + int returnChar = super.LA(i); + if (returnChar == CharStream.EOF) { + return returnChar; + } else if (returnChar == 0) { + return returnChar; + } + + return Character.toUpperCase((char) returnChar); + } + } + }
