You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tajo.apache.org by hy...@apache.org on 2013/07/29 06:03:31 UTC

[02/13] TAJO-87: Integration of tajo algebra module and SQL parser

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/00c3ee2b/tajo-frontend/tajo-frontend-sql/src/main/java/org/apache/tajo/frontend/sql/SQLAnalyzer.java
----------------------------------------------------------------------
diff --git a/tajo-frontend/tajo-frontend-sql/src/main/java/org/apache/tajo/frontend/sql/SQLAnalyzer.java b/tajo-frontend/tajo-frontend-sql/src/main/java/org/apache/tajo/frontend/sql/SQLAnalyzer.java
deleted file mode 100644
index 9157d44..0000000
--- a/tajo-frontend/tajo-frontend-sql/src/main/java/org/apache/tajo/frontend/sql/SQLAnalyzer.java
+++ /dev/null
@@ -1,932 +0,0 @@
-/**
- * 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.frontend.sql;
-
-import com.google.common.base.Preconditions;
-import org.antlr.runtime.ANTLRStringStream;
-import org.antlr.runtime.CommonTokenStream;
-import org.antlr.runtime.RecognitionException;
-import org.antlr.runtime.tree.CommonTree;
-import org.antlr.runtime.tree.Tree;
-import org.apache.tajo.algebra.*;
-import org.apache.tajo.algebra.Aggregation.GroupElement;
-import org.apache.tajo.algebra.Aggregation.GroupType;
-import org.apache.tajo.algebra.LiteralExpr.LiteralType;
-import org.apache.tajo.algebra.Sort.SortSpec;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import static org.apache.tajo.algebra.CreateTable.ColumnDefinition;
-
-public class SQLAnalyzer {
-
-  public Expr parse(String sql) throws SQLSyntaxError {
-    ParsingContext context = new ParsingContext(sql);
-    CommonTree tree = parseSQL(sql);
-    return transform(context, tree);
-  }
-
-  private static class ParsingContext {
-    private String rawQuery;
-    public ParsingContext(String sql) {
-      this.rawQuery = sql;
-    }
-  }
-
-  public static CommonTree parseSQL(String sql) {
-    ANTLRStringStream input = new ANTLRStringStream(sql);
-    SQLLexer lexer = new SQLLexer(input);
-    CommonTokenStream tokens = new CommonTokenStream(lexer);
-    SQLParser parser = new SQLParser(tokens);
-
-    CommonTree ast;
-    try {
-      ast = ((CommonTree) parser.statement().getTree());
-    } catch (RecognitionException e) {
-      throw new SQLParseError(e.getMessage());
-    }
-
-    return ast;
-  }
-
-  Expr transform(ParsingContext context, CommonTree ast) throws SQLSyntaxError {
-    switch (ast.getType()) {
-      case SQLParser.SELECT:
-        return parseSelectStatement(context, ast);
-
-      case SQLParser.UNION:
-      case SQLParser.EXCEPT:
-      case SQLParser.INTERSECT:
-        return parseSetStatement(context, ast);
-
-      case SQLParser.INSERT:
-
-      case SQLParser.CREATE_INDEX:
-
-      case SQLParser.CREATE_TABLE:
-        return parseCreateStatement(context, ast);
-
-      case SQLParser.DROP_TABLE:
-
-      default:
-        return null;
-    }
-  }
-
-  /**
-   * t=table ASSIGN select_stmt -> ^(CREATE_TABLE $t select_stmt)
-   * | CREATE TABLE t=table AS select_stmt -> ^(CREATE_TABLE $t select_stmt)
-   *
-   * @param ast
-   * @return
-   */
-  private CreateTable parseCreateStatement(final ParsingContext context,
-                                               final CommonTree ast) throws SQLSyntaxError {
-    CreateTable createTable;
-
-    int idx = 0;
-    CommonTree node;
-    String tableName = ast.getChild(idx).getText();
-    idx++;
-
-    boolean external = false;
-    ColumnDefinition [] tableElements = null;
-    String storeType = null;
-    Map<String, String> params = null;
-    Expr nestedAlgebra = null;
-    String location = null;
-    while(idx < ast.getChildCount()) {
-      node = (CommonTree) ast.getChild(idx);
-      switch (node.getType()) {
-        case SQLParser.EXTERNAL:
-          external = true;
-          break;
-
-        case SQLParser.TABLE_DEF:
-          tableElements = parseTableElementList(node);
-          break;
-
-        case SQLParser.USING:
-          storeType = node.getChild(0).getText();
-          break;
-
-        case SQLParser.PARAMS:
-          params = parseParams(node);
-          break;
-
-        case SQLParser.AS:
-          nestedAlgebra = parseSelectStatement(context, node.getChild(0));
-          break;
-
-        case SQLParser.LOCATION:
-          location = node.getChild(0).getText();
-          break;
-
-        default:
-          throw new SQLSyntaxError(context.rawQuery, "ERROR: not yet supported query");
-      }
-      idx++;
-    }
-
-    if (nestedAlgebra != null) {
-      createTable = new CreateTable(tableName, nestedAlgebra);
-    } else {
-      createTable = new CreateTable(tableName);
-      if (external) {
-        if (location != null) {
-          createTable.setLocation(location);
-        }
-      }
-    }
-
-    if (tableElements != null) {
-      createTable.setTableElements(tableElements);
-    }
-
-    if (storeType != null) {
-      createTable.setStorageType(storeType);
-      if (params != null) {
-        createTable.setParams(params);
-      }
-    }
-
-    // constraints
-    if (external && location == null) {
-      throw new SQLSyntaxError(context.rawQuery,
-          "CREATE EXTERNAL TABLE statement requires LOCATION clause.");
-    }
-    if (!external && location != null) {
-      throw new SQLSyntaxError(context.rawQuery,
-          "LOCATION clause can be only used in CREATE EXTERNAL TABLE statement.");
-    }
-    if (tableElements == null && location != null) {
-      throw new SQLSyntaxError(context.rawQuery,
-          "LOCATION clause requires a schema definition.");
-    }
-
-    return createTable;
-  }
-
-  private ColumnDefinition [] parseTableElementList(final CommonTree ast) {
-    ColumnDefinition [] tableDef = new ColumnDefinition[ast.getChildCount()];
-    for (int i = 0; i < ast.getChildCount(); i++) {
-      tableDef[i] = new ColumnDefinition(ast.getChild(i).getChild(0).getText(),
-          ast.getChild(i).getChild(1).getText());;
-    }
-
-    return tableDef;
-  }
-
-  /**
-   * Should be given Params Node
-   *
-   * EBNF: WITH LEFT_PAREN param (COMMA param)* RIGHT_PAREN
-   * AST: ^(PARAMS param+)
-   *
-   * @param ast
-   * @return
-   */
-  private static Map<String,String> parseParams(final CommonTree ast) {
-    Map<String, String> params = new HashMap<String, String>();
-
-    Tree child;
-    for (int i = 0; i < ast.getChildCount(); i++) {
-      child = ast.getChild(i);
-      params.put(child.getChild(0).getText(), child.getChild(1).getText());
-    }
-    return params;
-  }
-
-  private Expr parseSelectStatement(final ParsingContext context, final Tree ast) throws SQLSyntaxError {
-    CommonTree node;
-    QueryBlock block = new QueryBlock();
-    for (int cur = 0; cur < ast.getChildCount(); cur++) {
-      node = (CommonTree) ast.getChild(cur);
-
-      switch (node.getType()) {
-        case SQLParser.FROM:
-          Expr fromClause = parseFromClause(context, node);
-          block.setTableExpression(fromClause);
-          break;
-
-        case SQLParser.SET_QUALIFIER:
-          if (parseSetQualifier(node)) {
-            block.setDistinct();
-          }
-          break;
-
-        case SQLParser.SEL_LIST:
-          Projection projection = parseSelectList(context, node);
-          block.setProjection(projection);
-          break;
-
-        case SQLParser.WHERE:
-          block.setSearchCondition(parseWhereClause(context, node));
-          break;
-
-        case SQLParser.GROUP_BY:
-          Aggregation aggregation = parseGroupByClause(node);
-          block.setAggregation(aggregation);
-          break;
-
-        case SQLParser.HAVING:
-          Expr expr = parseHavingClause(context, node);
-          block.setHavingCondition(expr);
-          break;
-
-        case SQLParser.ORDER_BY:
-          SortSpec [] sortSpecs = parseSortSpecifiers(node.getChild(0));
-          block.setSort(new Sort(sortSpecs));
-          break;
-
-        case SQLParser.LIMIT:
-          block.setLimit(parseLimitClause(context, node));
-          break;
-
-        default:
-      }
-    }
-
-    return transformQueryBlock(context, block);
-  }
-
-  /**
-   * There is an algebraic order of a QueryBlock.
-   * Relation (or Join) -> Selection -> Aggregation -> Sort -> Limit
-   *
-   * @param context
-   * @param block
-   * @return
-   */
-  private Expr transformQueryBlock(ParsingContext context, QueryBlock block) throws SQLSyntaxError {
-    Expr current = null;
-
-    // Selection
-    if (block.hasTableExpression()) {
-      current = block.getTableExpression();
-    }
-
-    if (block.hasSearchCondition()) {
-      if (current == null) {
-        throw new SQLSyntaxError(context.rawQuery,
-            "No TableExpression, but there exists search condition");
-      }
-      Selection selection = new Selection(current, block.getSearchCondition());
-      current = selection;
-    }
-
-    // Aggregation
-    Aggregation aggregation = null;
-    if (block.hasAggregation()) {
-      if (current == null) {
-        throw new SQLSyntaxError(context.rawQuery,
-            "No TableExpression, but there exists a group-by clause");
-      }
-      aggregation = block.getAggregation();
-
-      if (block.hasAggregation()) {
-        aggregation.setHavingCondition(block.getHavingCondition());
-      }
-
-      aggregation.setChild(current);
-      current = aggregation;
-    }
-
-    if (block.hasSort()) {
-      if (current == null) {
-        throw new SQLSyntaxError(context.rawQuery,
-            "No TableExpression, but there exists a sort clause");
-      }
-      Sort sort = block.getSort();
-      sort.setChild(current);
-      current = sort;
-    }
-
-    if (block.hasLimit()) {
-      if (current == null) {
-        throw new SQLSyntaxError(context.rawQuery,
-            "No TableExpression, but there exists a limit clause");
-      }
-      Limit limit = block.getLimit();
-      limit.setChild(current);
-      current = limit;
-    }
-
-    Projection projection = block.getProjection();
-    if (block.hasAggregation()) {
-      aggregation.setTargets(projection.getTargets());
-    } else {
-      if (block.isDistinct()) {
-        projection.setDistinct();
-      }
-      if (current != null) {
-        projection.setChild(current);
-      }
-      current = projection;
-    }
-
-    return current;
-  }
-
-  private Expr parseSetStatement(final ParsingContext context,
-                                 final CommonTree ast) throws SQLSyntaxError {
-    Expr left;
-    Expr right;
-
-    ExprType type = tokenToExprType(ast.getType());
-
-    int idx = 0;
-    left = transform(context, (CommonTree) ast.getChild(idx));
-    idx++;
-    int nodeType = ast.getChild(idx).getType();
-    boolean distinct = true; // distinct is default in ANSI SQL standards
-    if (nodeType == SQLParser.ALL) {
-      distinct = true;
-      idx++;
-    } else if (nodeType == SQLParser.DISTINCT) {
-      distinct = false;
-      idx++;
-    }
-    right = transform(context, (CommonTree) ast.getChild(idx));
-    return new SetOperation(type, left, right, distinct);
-  }
-
-  /**
-   * @return true if SELECT DISTINCT. Otherwise, it will be false.
-   */
-  private boolean parseSetQualifier(final CommonTree ast) {
-    int idx = 0;
-
-    if (ast.getChild(idx).getType() == SQLParser.DISTINCT) {
-      return true;
-    } else {
-      return false;
-    }
-  }
-
-  private Expr parseHavingClause(final ParsingContext context, final CommonTree ast)
-      throws SQLSyntaxError {
-    return createExpression(context, ast.getChild(0));
-  }
-
-  private Limit parseLimitClause(final ParsingContext context, final CommonTree ast)
-      throws SQLSyntaxError {
-    Expr expr = createExpression(context, ast.getChild(0));
-
-    if (expr instanceof LiteralExpr) {
-      Limit limitClause = new Limit(expr);
-      return limitClause;
-    }
-
-    throw new SQLSyntaxError(context.rawQuery, "LIMIT clause cannot have the parameter "
-        + expr);
-  }
-
-  /**
-   * Should be given SortSpecifiers Node
-   *
-   * EBNF: sort_specifier (COMMA sort_specifier)* -> sort_specifier+
-   *
-   * @param ast
-   */
-  private SortSpec[] parseSortSpecifiers(final Tree ast) {
-    int numSortKeys = ast.getChildCount();
-    SortSpec[] sortSpecs = new SortSpec[numSortKeys];
-    CommonTree node;
-    ColumnReferenceExpr column;
-
-    // Each child has the following EBNF and AST:
-    // EBNF: fn=fieldName a=order_specification? o=null_ordering?
-    // AST: ^(SORT_KEY $fn $a? $o?)
-    for (int i = 0; i < numSortKeys; i++) {
-      node = (CommonTree) ast.getChild(i);
-      column = checkAndGetColumnByAST(node.getChild(0));
-      sortSpecs[i] = new SortSpec(column);
-
-      if (node.getChildCount() > 1) {
-        Tree child;
-        for (int j = 1; j < node.getChildCount(); j++) {
-          child = node.getChild(j);
-
-          // AST: ^(ORDER ASC) | ^(ORDER DESC)
-          if (child.getType() == SQLParser.ORDER) {
-            if (child.getChild(0).getType() == SQLParser.DESC) {
-              sortSpecs[i].setDescending();
-            }
-          } else if (child.getType() == SQLParser.NULL_ORDER) {
-            // AST: ^(NULL_ORDER FIRST) | ^(NULL_ORDER LAST)
-            if (child.getChild(0).getType() == SQLParser.FIRST) {
-              sortSpecs[i].setNullFirst();
-            }
-          }
-        }
-      }
-    }
-
-    return sortSpecs;
-  }
-
-  /**
-   * See 'groupby_clause' rule in SQL.g
-   *
-   * @param ast
-   */
-  private Aggregation parseGroupByClause(final CommonTree ast) {
-    int idx = 0;
-    Aggregation clause = new Aggregation();
-    if (ast.getChild(idx).getType() == SQLParser.EMPTY_GROUPING_SET) {
-
-    } else {
-      // the remain ones are grouping fields.
-      Tree group;
-      List<ColumnReferenceExpr> columnRefs = new ArrayList<ColumnReferenceExpr>();
-      ColumnReferenceExpr[] columns;
-      ColumnReferenceExpr column;
-      List<GroupElement> groups = new ArrayList<GroupElement>();
-      for (; idx < ast.getChildCount(); idx++) {
-        group = ast.getChild(idx);
-        switch (group.getType()) {
-          case SQLParser.CUBE:
-            columns = parseColumnReferences((CommonTree) group);
-            GroupElement cube = new GroupElement(GroupType.CUBE, columns);
-            groups.add(cube);
-            break;
-
-          case SQLParser.ROLLUP:
-            columns = parseColumnReferences((CommonTree) group);
-            GroupElement rollup = new GroupElement(GroupType.ROLLUP, columns);
-            groups.add(rollup);
-            break;
-
-          case SQLParser.FIELD_NAME:
-            column = checkAndGetColumnByAST(group);
-            columnRefs.add(column);
-            break;
-        }
-      }
-
-      if (columnRefs.size() > 0) {
-        ColumnReferenceExpr[] groupingFields = columnRefs.toArray(new ColumnReferenceExpr[columnRefs.size()]);
-        GroupElement g = new GroupElement(GroupType.GROUPBY, groupingFields);
-        groups.add(g);
-      }
-
-      clause.setGroups(groups.toArray(new GroupElement[groups.size()]));
-    }
-    return clause;
-  }
-
-
-
-  /**
-   * It parses the below EBNF.
-   * <pre>
-   * column_reference
-   * : fieldName (COMMA fieldName)* -> fieldName+
-   * ;
-   * </pre>
-   * @param parent
-   * @return
-   */
-  private ColumnReferenceExpr[] parseColumnReferences(final CommonTree parent) {
-    ColumnReferenceExpr[] columns = new ColumnReferenceExpr[parent.getChildCount()];
-
-    for (int i = 0; i < columns.length; i++) {
-      columns[i] = checkAndGetColumnByAST(parent.getChild(i));
-    }
-
-    return columns;
-  }
-
-  private Expr parseWhereClause(final ParsingContext context, final CommonTree ast)
-      throws SQLSyntaxError {
-    return createExpression(context, ast.getChild(0));
-  }
-
-  /**
-   * This method parses the select list of a query statement.
-   * <pre>
-   * EBNF:
-   *
-   * selectList
-   * : MULTIPLY -> ^(SEL_LIST ALL)
-   * | derivedColumn (COMMA derivedColumn)* -> ^(SEL_LIST derivedColumn+)
-   * ;
-   *
-   * derivedColumn
-   * : bool_expr asClause? -> ^(COLUMN bool_expr asClause?)
-   * ;
-   *
-   * @param ast
-   */
-  private Projection parseSelectList(ParsingContext context, final CommonTree ast)
-      throws SQLSyntaxError {
-    Projection projection = new Projection();
-    if (ast.getChild(0).getType() == SQLParser.ALL) {
-      projection.setAll();
-    } else {
-      CommonTree node;
-      int numTargets = ast.getChildCount();
-      Target [] targets = new Target[numTargets];
-      Expr evalTree;
-      String alias;
-
-      // the final one for each target is the alias
-      // EBNF: bool_expr AS? fieldName
-      for (int i = 0; i < ast.getChildCount(); i++) {
-        node = (CommonTree) ast.getChild(i);
-        evalTree = createExpression(context, node);
-        targets[i] = new Target(evalTree);
-        if (node.getChildCount() > 1) {
-          alias = node.getChild(node.getChildCount() - 1).getChild(0).getText();
-          targets[i].setAlias(alias);
-        }
-      }
-      projection.setTargets(targets);
-    }
-
-    return projection;
-  }
-
-  /**
-   * EBNF: table_list -> tableRef (COMMA tableRef)
-   * @param ast
-   */
-  private Expr parseFromClause(ParsingContext context, final CommonTree ast) throws SQLSyntaxError {
-    Expr previous = null;
-    CommonTree node;
-    for (int i = 0; i < ast.getChildCount(); i++) {
-      node = (CommonTree) ast.getChild(i);
-
-      switch (node.getType()) {
-
-        case SQLParser.TABLE:
-          // table (AS ID)?
-          // 0 - a table name, 1 - table alias
-          if (previous != null) {
-            Expr inner = parseTable(node);
-            Join newJoin = new Join(JoinType.INNER);
-            newJoin.setLeft(previous);
-            newJoin.setRight(inner);
-            previous = newJoin;
-          } else {
-            previous = parseTable(node);
-          }
-          break;
-        case SQLParser.JOIN:
-          Join newJoin = parseExplicitJoinClause(context, node);
-          newJoin.setLeft(previous);
-          previous = newJoin;
-          break;
-
-        case SQLParser.SUBQUERY:
-          Expr nestedAlgebra = parseSelectStatement(context, node.getChild(0));
-          String alias = node.getChild(1).getText();
-          previous = new TableSubQuery(alias, nestedAlgebra);
-          break;
-
-        default:
-          throw new SQLSyntaxError(context.rawQuery, "Wrong From Clause");
-      } // switch
-    } // for each derievedTable
-
-    return previous;
-  }
-
-  private Relation parseTable(final CommonTree tableAST) {
-    String tableName = tableAST.getChild(0).getText();
-    Relation table = new Relation(tableName);
-
-    if (tableAST.getChildCount() > 1) {
-      table.setAlias(tableAST.getChild(1).getText());
-    }
-
-    return table;
-  }
-
-  private Join parseExplicitJoinClause(ParsingContext ctx, final CommonTree ast)
-      throws SQLSyntaxError {
-
-    int idx = 0;
-    int parsedJoinType = ast.getChild(idx).getType();
-
-    Join joinClause;
-
-    switch (parsedJoinType) {
-      case SQLParser.CROSS:
-      case SQLParser.UNION:
-        joinClause = parseCrossAndUnionJoin(ast);
-        break;
-
-      case SQLParser.NATURAL:
-        joinClause = parseNaturalJoinClause(ctx, ast);
-        break;
-
-      case SQLParser.INNER:
-      case SQLParser.OUTER:
-        joinClause = parseQualifiedJoinClause(ctx, ast, 0);
-        break;
-
-      default: // default join (without join type) is inner join
-        joinClause = parseQualifiedJoinClause(ctx, ast, 0);
-    }
-
-    return joinClause;
-  }
-
-  private Join parseNaturalJoinClause(ParsingContext ctx, Tree ast) throws SQLSyntaxError {
-    Join join = parseQualifiedJoinClause(ctx, ast, 1);
-    join.setNatural();
-    return join;
-  }
-
-  private Join parseQualifiedJoinClause(ParsingContext context, final Tree ast, final int idx)
-      throws SQLSyntaxError {
-    int childIdx = idx;
-    Join join = null;
-
-    if (ast.getChild(childIdx).getType() == SQLParser.TABLE) { // default join
-      join = new Join(JoinType.INNER);
-      join.setRight(parseTable((CommonTree) ast.getChild(childIdx)));
-
-    } else {
-
-      if (ast.getChild(childIdx).getType() == SQLParser.INNER) {
-        join = new Join(JoinType.INNER);
-
-      } else if (ast.getChild(childIdx).getType() == SQLParser.OUTER) {
-
-        switch (ast.getChild(childIdx).getChild(0).getType()) {
-          case SQLParser.LEFT:
-            join = new Join(JoinType.LEFT_OUTER);
-            break;
-          case SQLParser.RIGHT:
-            join = new Join(JoinType.RIGHT_OUTER);
-            break;
-          case SQLParser.FULL:
-            join = new Join(JoinType.FULL_OUTER);
-            break;
-          default:
-            throw new SQLSyntaxError(context.rawQuery, "Unknown Join Type");
-        }
-      }
-
-      childIdx++;
-      join.setRight(parseTable((CommonTree) ast.getChild(childIdx)));
-    }
-
-    childIdx++;
-
-    if (ast.getChildCount() > childIdx) {
-      CommonTree joinQual = (CommonTree) ast.getChild(childIdx);
-
-      if (joinQual.getType() == SQLParser.ON) {
-        Expr joinCond = parseJoinCondition(context, joinQual);
-        join.setQual(joinCond);
-
-      } else if (joinQual.getType() == SQLParser.USING) {
-        ColumnReferenceExpr[] joinColumns = parseJoinColumns(joinQual);
-        join.setJoinColumns(joinColumns);
-      }
-    }
-
-    return join;
-  }
-
-  private Join parseCrossAndUnionJoin(Tree ast) {
-    JoinType joinType;
-
-    if (ast.getChild(0).getType() == SQLParser.CROSS) {
-      joinType = JoinType.CROSS_JOIN;
-    } else if (ast.getChild(0).getType() == SQLParser.UNION) {
-      joinType = JoinType.UNION;
-    } else {
-      throw new IllegalStateException("Neither the AST has cross join or union join:\n"
-          + ast.toStringTree());
-    }
-
-    Join join = new Join(joinType);
-    Preconditions.checkState(ast.getChild(1).getType() == SQLParser.TABLE);
-    join.setRight(parseTable((CommonTree) ast.getChild(1)));
-
-    return join;
-  }
-
-  private ColumnReferenceExpr[] parseJoinColumns(final CommonTree ast) {
-    ColumnReferenceExpr[] joinColumns = new ColumnReferenceExpr[ast.getChildCount()];
-
-    for (int i = 0; i < ast.getChildCount(); i++) {
-      joinColumns[i] = checkAndGetColumnByAST(ast.getChild(i));
-    }
-    return joinColumns;
-  }
-
-  private Expr parseJoinCondition(ParsingContext context, CommonTree ast) throws SQLSyntaxError {
-    return createExpression(context, ast.getChild(0));
-  }
-
-  private ColumnReferenceExpr checkAndGetColumnByAST(final Tree fieldNode) {
-    Preconditions.checkArgument(SQLParser.FIELD_NAME == fieldNode.getType());
-
-    String columnName = fieldNode.getChild(0).getText();
-    ColumnReferenceExpr column = new ColumnReferenceExpr(columnName);
-
-    String tableName = null;
-    if (fieldNode.getChildCount() > 1) {
-      tableName = fieldNode.getChild(1).getText();
-      column.setRelationName(tableName);
-    }
-
-    return column;
-  }
-
-  /**
-   * The EBNF of case statement
-   * <pre>
-   * searched_case
-   * : CASE s=searched_when_clauses e=else_clause END -> ^(CASE $s $e)
-   * ;
-   *
-   * searched_when_clauses
-   * : searched_when_clause searched_when_clause* -> searched_when_clause+
-   * ;
-   *
-   * searched_when_clause
-   * : WHEN c=search_condition THEN r=result -> ^(WHEN $c $r)
-   * ;
-   *
-   * else_clause
-   * : ELSE r=result -> ^(ELSE $r)
-   * ;
-   * </pre>
-   * @param tree
-   * @return
-   */
-  public CaseWhenExpr parseCaseWhen(ParsingContext context, final Tree tree) throws SQLSyntaxError {
-    int idx = 0;
-
-    CaseWhenExpr caseEval = new CaseWhenExpr();
-    Expr cond;
-    Expr thenResult;
-    Tree when;
-
-    for (; idx < tree.getChildCount() &&
-        tree.getChild(idx).getType() == SQLParser.WHEN; idx++) {
-
-      when = tree.getChild(idx);
-      cond = createExpression(context, when.getChild(0));
-      thenResult = createExpression(context, when.getChild(1));
-      caseEval.addWhen(cond, thenResult);
-    }
-
-    if (tree.getChild(idx) != null &&
-        tree.getChild(idx).getType() == SQLParser.ELSE) {
-      Expr elseResult = createExpression(context, tree.getChild(idx).getChild(0));
-      caseEval.setElseResult(elseResult);
-    }
-
-    return caseEval;
-  }
-
-  /**
-   * <pre>
-   * like_predicate : fieldName NOT? LIKE string_value_expr
-   * -> ^(LIKE NOT? fieldName string_value_expr)
-   * </pre>
-   * @param tree
-   * @return
-   */
-  private LikeExpr parseLike(ParsingContext context, final Tree tree) throws SQLSyntaxError {
-    int idx = 0;
-
-    boolean not = false;
-    if (tree.getChild(idx).getType() == SQLParser.NOT) {
-      not = true;
-      idx++;
-    }
-
-    ColumnReferenceExpr field = (ColumnReferenceExpr) createExpression(context, tree.getChild(idx));
-    idx++;
-    Expr pattern = createExpression(context, tree.getChild(idx));
-
-    return new LikeExpr(not, field, pattern);
-  }
-
-  public Expr createExpression(final ParsingContext context, final Tree ast) throws SQLSyntaxError {
-    switch(ast.getType()) {
-
-      // constants
-      case SQLParser.Unsigned_Integer:
-        return new LiteralExpr(ast.getText(), LiteralType.Unsigned_Integer);
-      case SQLParser.Unsigned_Float:
-        return new LiteralExpr(ast.getText(), LiteralType.Unsigned_Float);
-      case SQLParser.Unsigned_Large_Integer:
-        return new LiteralExpr(ast.getText(), LiteralType.Unsigned_Large_Integer);
-
-      case SQLParser.Character_String_Literal:
-        return new LiteralExpr(ast.getText(), LiteralType.String);
-
-      // unary expression
-      case SQLParser.NOT:
-        ;
-
-      // binary expressions
-      case SQLParser.LIKE:
-        return parseLike(context, ast);
-
-      case SQLParser.IS:
-        break;
-
-      case SQLParser.AND:
-      case SQLParser.OR:
-      case SQLParser.Equals_Operator:
-      case SQLParser.Not_Equals_Operator:
-      case SQLParser.Less_Than_Operator:
-      case SQLParser.Less_Or_Equals_Operator:
-      case SQLParser.Greater_Than_Operator:
-      case SQLParser.Greater_Or_Equals_Operator:
-      case SQLParser.Plus_Sign:
-      case SQLParser.Minus_Sign:
-      case SQLParser.Asterisk:
-      case SQLParser.Slash:
-      case SQLParser.Percent:
-        return new BinaryOperator(tokenToExprType(ast.getType()),
-            createExpression(context, ast.getChild(0)),
-            createExpression(context, ast.getChild(1)));
-
-      // others
-      case SQLParser.COLUMN:
-        return createExpression(context, ast.getChild(0));
-
-      case SQLParser.FIELD_NAME:
-        return checkAndGetColumnByAST(ast);
-
-      case SQLParser.FUNCTION:
-        String signature = ast.getText();
-        FunctionExpr func = new FunctionExpr(signature);
-        Expr[] givenArgs = new Expr[ast.getChildCount()];
-
-        for (int i = 0; i < ast.getChildCount(); i++) {
-          givenArgs[i] = createExpression(context, ast.getChild(i));
-        }
-        func.setParams(givenArgs);
-
-        break;
-      case SQLParser.COUNT_VAL:
-
-      case SQLParser.COUNT_ROWS:
-
-
-      case SQLParser.CASE:
-        return parseCaseWhen(context, ast);
-
-      case SQLParser.SUBQUERY: // ^(SUBQUERY subquery)
-        return new ScalarSubQuery(parseSelectStatement(context, ast.getChild(0)));
-
-      default:
-    }
-    return null;
-  }
-
-  public static ExprType tokenToExprType(int tokenId) {
-    switch (tokenId) {
-      case SQLParser.UNION: return ExprType.Union;
-      case SQLParser.EXCEPT: return ExprType.Except;
-      case SQLParser.INTERSECT: return ExprType.Intersect;
-
-      case SQLParser.AND: return ExprType.And;
-      case SQLParser.OR: return ExprType.Or;
-      case SQLParser.Equals_Operator: return ExprType.Equals;
-      case SQLParser.Less_Than_Operator: return ExprType.LessThan;
-      case SQLParser.Less_Or_Equals_Operator: return ExprType.LessThan;
-      case SQLParser.Greater_Than_Operator: return ExprType.GreaterThan;
-      case SQLParser.Greater_Or_Equals_Operator: return ExprType.GreaterThanOrEquals;
-      case SQLParser.Plus_Sign: return ExprType.Plus;
-      case SQLParser.Minus_Sign: return ExprType.Minus;
-      case SQLParser.Asterisk: return ExprType.Multiply;
-      case SQLParser.Slash: return ExprType.Divide;
-      case SQLParser.Percent: return ExprType.Mod;
-
-      default: throw new RuntimeException("Unknown Token Id: " + tokenId);
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/00c3ee2b/tajo-frontend/tajo-frontend-sql/src/main/java/org/apache/tajo/frontend/sql/SQLParseError.java
----------------------------------------------------------------------
diff --git a/tajo-frontend/tajo-frontend-sql/src/main/java/org/apache/tajo/frontend/sql/SQLParseError.java b/tajo-frontend/tajo-frontend-sql/src/main/java/org/apache/tajo/frontend/sql/SQLParseError.java
deleted file mode 100644
index d3d6d91..0000000
--- a/tajo-frontend/tajo-frontend-sql/src/main/java/org/apache/tajo/frontend/sql/SQLParseError.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/**
- * 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.frontend.sql;
-
-
-@SuppressWarnings("UnusedDeclaration")
-public class SQLParseError extends RuntimeException {
-  public SQLParseError(String parseErrorMessage) {
-    super(parseErrorMessage);
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/00c3ee2b/tajo-frontend/tajo-frontend-sql/src/main/java/org/apache/tajo/frontend/sql/SQLSyntaxError.java
----------------------------------------------------------------------
diff --git a/tajo-frontend/tajo-frontend-sql/src/main/java/org/apache/tajo/frontend/sql/SQLSyntaxError.java b/tajo-frontend/tajo-frontend-sql/src/main/java/org/apache/tajo/frontend/sql/SQLSyntaxError.java
deleted file mode 100644
index 0aa1276..0000000
--- a/tajo-frontend/tajo-frontend-sql/src/main/java/org/apache/tajo/frontend/sql/SQLSyntaxError.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/**
- * 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.frontend.sql;
-
-
-public class SQLSyntaxError extends Exception {
-	private static final long serialVersionUID = 5388279335175632066L;
-
-  private String query;
-  private String errorMessage;
-  private String detailedMessage;
-
-	public SQLSyntaxError(String query, String errorMessage) {
-    this.query = query;
-    this.errorMessage = errorMessage;
-	}
-
-  @Override
-  public String getMessage() {
-    if (detailedMessage == null) {
-      StringBuilder sb = new StringBuilder();
-      sb.append("ERROR: " + errorMessage).append("\n");
-      sb.append("LINE: " + query);
-      detailedMessage = sb.toString();
-    }
-
-    return detailedMessage;
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/00c3ee2b/tajo-frontend/tajo-frontend-sql/src/test/java/org/apache/tajo/frontend/sql/TestSQLAnalyzer.java
----------------------------------------------------------------------
diff --git a/tajo-frontend/tajo-frontend-sql/src/test/java/org/apache/tajo/frontend/sql/TestSQLAnalyzer.java b/tajo-frontend/tajo-frontend-sql/src/test/java/org/apache/tajo/frontend/sql/TestSQLAnalyzer.java
deleted file mode 100644
index 7f3755c..0000000
--- a/tajo-frontend/tajo-frontend-sql/src/test/java/org/apache/tajo/frontend/sql/TestSQLAnalyzer.java
+++ /dev/null
@@ -1,572 +0,0 @@
-/**
- * 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.frontend.sql;
-
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.apache.tajo.algebra.*;
-import org.apache.tajo.algebra.Aggregation.GroupElement;
-
-import static junit.framework.Assert.*;
-import static org.apache.tajo.algebra.Aggregation.GroupType;
-
-public class TestSQLAnalyzer {
-  private static SQLAnalyzer analyzer = null;
-
-  @BeforeClass
-  public static void setup() {
-    analyzer = new SQLAnalyzer();
-  }
-
-  private String[] QUERIES = {
-      "select id, name, score, age from people", // 0
-      "select name, score, age from people where score > 30", // 1
-      "select name, score, age from people where 3 + 5 * 3", // 2
-      "select age, sumtest(score) as total from people group by age having sumtest(score) > 30", // 3
-      "select p.id, s.id, score, dept from people as p, student as s where p.id = s.id", // 4
-      "select name, score from people order by score asc, age desc null first", // 5
-      // only expr
-      "select 7 + 8 as total", // 6
-      // limit test
-      "select id, name, score, age from people limit 3" // 7
-  };
-
-  @Test
-  public final void testSelectStatement() throws SQLSyntaxError {
-    Expr expr = analyzer.parse(QUERIES[0]);
-    assertEquals(ExprType.Projection, expr.getType());
-    Projection projection = (Projection) expr;
-    assertEquals(ExprType.Relation, projection.getChild().getType());
-    Relation relation = (Relation) projection.getChild();
-    assertEquals("people", relation.getName());
-  }
-
-  @Test
-  public final void testSelectStatementWithAlias() throws SQLSyntaxError {
-    Expr expr = analyzer.parse(QUERIES[4]);
-    assertEquals(ExprType.Projection, expr.getType());
-    Projection projection = (Projection) expr;
-    assertEquals(ExprType.Selection, projection.getChild().getType());
-    Selection selection = (Selection) projection.getChild();
-    assertEquals(ExprType.Join, selection.getChild().getType());
-    Join join = (Join) selection.getChild();
-    assertEquals(ExprType.Relation, join.getLeft().getType());
-    Relation outer = (Relation) join.getLeft();
-    assertEquals("p", outer.getAlias());
-    assertEquals(ExprType.Relation, join.getRight().getType());
-    Relation inner = (Relation) join.getRight();
-    assertEquals("s", inner.getAlias());
-  }
-
-  @Test
-  public final void testOrderByClause() throws SQLSyntaxError {
-    Expr block = analyzer.parse(QUERIES[5]);
-    testOrderByCluse(block);
-  }
-
-  @Test
-  public final void testOnlyExpr() throws SQLSyntaxError {
-    Expr expr = analyzer.parse(QUERIES[6]);
-    assertEquals(ExprType.Projection, expr.getType());
-    Projection projection = (Projection) expr;
-    assertEquals(1, projection.getTargets().length);
-    Target target = projection.getTargets()[0];
-    assertEquals("total", target.getAlias());
-    assertEquals(ExprType.Plus, target.getExpr().getType());
-  }
-
-  @Test
-  public void testLimit() throws SQLSyntaxError {
-    Expr expr = analyzer.parse(QUERIES[7]);
-    assertEquals(ExprType.Projection, expr.getType());
-    Projection projection = (Projection) expr;
-    assertEquals(ExprType.Limit, projection.getChild().getType());
-  }
-
-  private String[] GROUP_BY = {
-      "select age, sumtest(score) as total from people group by age having sumtest(score) > 30", // 0
-      "select name, age, sumtest(score) total from people group by cube (name,age)", // 1
-      "select name, age, sumtest(score) total from people group by rollup (name,age)", // 2
-      "select id, name, age, sumtest(score) total from people group by id, cube (name), rollup (age)", // 3
-      "select id, name, age, sumtest(score) total from people group by ()", // 4
-  };
-
-  @Test
-  public final void testGroupByStatement() throws SQLSyntaxError {
-    Expr expr = analyzer.parse(GROUP_BY[0]);
-    assertEquals(ExprType.Aggregation, expr.getType());
-    Aggregation aggregation = (Aggregation) expr;
-
-    assertEquals(1, aggregation.getGroupSet().length);
-    assertEquals("age", aggregation.getGroupSet()[0].getColumns()[0].getName());
-    assertTrue(aggregation.hasHavingCondition());
-    assertEquals(ExprType.GreaterThan, aggregation.getHavingCondition().getType());
-  }
-
-  @Test
-  public final void testCubeByStatement() throws SQLSyntaxError {
-    Expr expr = analyzer.parse(GROUP_BY[1]);
-    assertEquals(ExprType.Aggregation, expr.getType());
-    Aggregation aggregation = (Aggregation) expr;
-    assertEquals(1, aggregation.getGroupSet().length);
-    assertEquals(GroupType.CUBE, aggregation.getGroupSet()[0].getType());
-    GroupElement[] groups = aggregation.getGroupSet();
-    assertEquals("name", groups[0].getColumns()[0].getName());
-    assertEquals("age", groups[0].getColumns()[1].getName());
-  }
-
-  @Test
-  public final void testRollUpStatement() throws SQLSyntaxError {
-    Expr expr = analyzer.parse(GROUP_BY[2]);
-    assertEquals(ExprType.Aggregation, expr.getType());
-    Aggregation aggregation = (Aggregation) expr;
-
-    assertEquals(1, aggregation.getGroupSet().length);
-    assertEquals(GroupType.ROLLUP, aggregation.getGroupSet()[0].getType());
-    GroupElement [] groups = aggregation.getGroupSet();
-    assertEquals("name", groups[0].getColumns()[0].getName());
-    assertEquals("age", groups[0].getColumns()[1].getName());
-  }
-
-  @Test
-  public final void testMixedGroupByStatement() throws SQLSyntaxError {
-    Expr expr = analyzer.parse(GROUP_BY[3]);
-    assertEquals(ExprType.Aggregation, expr.getType());
-    Aggregation aggregation = (Aggregation) expr;
-    assertEquals(3, aggregation.getGroupSet().length);
-    int gid = 0;
-    GroupElement group = aggregation.getGroupSet()[gid++];
-    assertEquals(GroupType.CUBE, group.getType());
-    assertEquals("name", group.getColumns()[0].getName());
-    group = aggregation.getGroupSet()[gid++];
-    assertEquals(GroupType.ROLLUP, group.getType());
-    assertEquals("age", group.getColumns()[0].getName());
-    group = aggregation.getGroupSet()[gid++];
-    assertEquals(GroupType.GROUPBY, group.getType());
-    assertEquals("id", group.getColumns()[0].getName());
-  }
-
-  @Test
-  public final void testEmptyGroupSetStatement() throws SQLSyntaxError {
-    Expr expr = analyzer.parse(GROUP_BY[4]);
-    assertEquals(ExprType.Aggregation, expr.getType());
-    Aggregation block = (Aggregation) expr;
-    assertTrue(block.isEmptyGrouping());
-  }
-
-
-  static String [] JOINS = {
-      "select p.id, name, branch_name from people as p natural join student natural join branch", // 0
-      "select name, dept from people as p inner join student as s on p.id = s.people_id", // 1
-      "select name, dept from people as p inner join student as s using (p.id)", // 2
-      "select p.id, name, branch_name from people as p cross join student cross join branch", // 3
-      "select p.id, dept from people as p left outer join student as s on p.id = s.people_id", // 4
-      "select p.id, dept from people as p right outer join student as s on p.id = s.people_id", // 5
-      "select p.id, dept from people as p join student as s on p.id = s.people_id", // 6
-      "select p.id, dept from people as p left join student as s on p.id = s.people_id", // 7
-      "select p.id, dept from people as p right join student as s on p.id= s.people_id", // 8
-      "select * from table1 " +
-          "cross join table2 " +
-          "join table3 on table1.id = table3.id " +
-          "inner join table4 on table1.id = table4.id " +
-          "left outer join table5 on table1.id = table5.id " +
-          "right outer join table6 on table1.id = table6.id " +
-          "full outer join table7 on table1.id = table7.id " +
-          "natural join table8 " +
-          "natural inner join table9 " +
-          "natural left outer join table10 " +
-          "natural right outer join table11 " +
-          "natural full outer join table12 ", // 9 - all possible join clauses*/
-      "select s_acctbal, s_name, n_name, p_partkey, p_mfgr, s_address, s_phone, s_comment, ps_supplycost " + // 10
-          "from region join nation on n_regionkey = r_regionkey and r_name = 'EUROPE' " +
-          "join supplier on s_nationekey = n_nationkey " +
-          "join partsupp on s_suppkey = ps_ps_suppkey " +
-          "join part on p_partkey = ps_partkey and p_type like '%BRASS' and p_size = 15"
-
-  };
-
-  @Test
-  /**
-   *           join
-   *          /    \
-   *       join    branch
-   *     /     \
-   * people  student
-   *
-   */
-  public final void testNaturalJoinClause() throws SQLSyntaxError {
-    Expr expr = analyzer.parse(JOINS[0]);
-
-
-    Join join = commonJoinTest(expr);
-    assertEquals(JoinType.INNER, join.getJoinType());
-    assertTrue(join.isNatural());
-    Relation branch = (Relation) join.getRight();
-    assertEquals("branch", branch.getName());
-    assertEquals(ExprType.Join, join.getLeft().getType());
-    Join leftJoin = (Join) join.getLeft();
-    Relation people = (Relation) leftJoin.getLeft();
-    Relation student = (Relation) leftJoin.getRight();
-    assertEquals("people", people.getName());
-    assertEquals("student", student.getName());
-  }
-
-  private Join commonJoinTest(Expr expr) {
-    assertEquals(ExprType.Projection, expr.getType());
-    Projection projection = (Projection) expr;
-
-    return (Join) projection.getChild();
-  }
-
-  @Test
-  /**
-   *       join
-   *     /      \
-   * people   student
-   *
-   */
-  public final void testInnerJoinClause() throws SQLSyntaxError {
-    Expr expr = analyzer.parse(JOINS[1]);
-
-    Join join = commonJoinTest(expr);
-    assertEquals(JoinType.INNER, join.getJoinType());
-    Relation people = (Relation) join.getLeft();
-    assertEquals("people", people.getName());
-    assertEquals("p", people.getAlias());
-
-    Relation student = (Relation) join.getRight();
-    assertEquals("student", student.getName());
-    assertEquals("s", student.getAlias());
-    assertTrue(join.hasQual());
-    assertEquals(ExprType.Equals, join.getQual().getType());
-
-    Expr expr2 = analyzer.parse(JOINS[2]);
-    join = commonJoinTest(expr2);
-    assertEquals(JoinType.INNER, join.getJoinType());
-    Relation people2 = (Relation) join.getLeft();
-    assertEquals("people", people2.getName());
-    assertEquals("p", people2.getAlias());
-    Relation student2 = (Relation) join.getRight();
-    assertEquals("student", student2.getName());
-    assertEquals("s", student2.getAlias());
-    assertTrue(join.hasJoinColumns());
-    assertEquals("id", join.getJoinColumns()[0].getName());
-  }
-
-  @Test
-  public final void testCrossJoinClause() throws SQLSyntaxError {
-    Expr expr = analyzer.parse(JOINS[3]);
-
-    Join join = commonJoinTest(expr);
-    assertEquals(JoinType.CROSS_JOIN, join.getJoinType());
-    Relation branch = (Relation) join.getRight();
-    assertEquals("branch", branch.getName());
-    assertEquals(ExprType.Join, join.getLeft().getType());
-    Join leftJoin = (Join) join.getLeft();
-    Relation people = (Relation) leftJoin.getLeft();
-    Relation student = (Relation) leftJoin.getRight();
-    assertEquals("people", people.getName());
-    assertEquals("student", student.getName());
-  }
-
-  @Test
-  public final void testLeftOuterJoinClause() throws SQLSyntaxError {
-    Expr expr = analyzer.parse(JOINS[4]);
-
-    Join join = commonJoinTest(expr);
-    assertEquals(JoinType.LEFT_OUTER, join.getJoinType());
-    Relation people = (Relation) join.getLeft();
-    assertEquals("people", people.getName());
-    assertEquals("p", people.getAlias());
-    Relation student = (Relation) join.getRight();
-    assertEquals("student", student.getName());
-    assertEquals("s", student.getAlias());
-    assertTrue(join.hasQual());
-    assertEquals(ExprType.Equals, join.getQual().getType());
-  }
-
-  @Test
-  public final void testRightOuterJoinClause() throws SQLSyntaxError {
-    Expr expr = analyzer.parse(JOINS[5]);
-
-    Join join = commonJoinTest(expr);
-    assertEquals(JoinType.RIGHT_OUTER, join.getJoinType());
-    Relation people = (Relation) join.getLeft();
-    assertEquals("people", people.getName());
-    assertEquals("p", people.getAlias());
-    Relation student = (Relation) join.getRight();
-    assertEquals("student", student.getName());
-    assertEquals("s", student.getAlias());
-    assertTrue(join.hasQual());
-    assertEquals(ExprType.Equals, join.getQual().getType());
-  }
-
-  @Test
-  public final void testLeftJoinClause() throws SQLSyntaxError {
-    Expr expr = analyzer.parse(JOINS[7]);
-
-    Join join = commonJoinTest(expr);
-    assertEquals(JoinType.LEFT_OUTER, join.getJoinType());
-    Relation people = (Relation) join.getLeft();
-    assertEquals("people", people.getName());
-    assertEquals("p", people.getAlias());
-    Relation student = (Relation) join.getRight();
-    assertEquals("student", student.getName());
-    assertEquals("s", student.getAlias());
-    assertTrue(join.hasQual());
-    assertEquals(ExprType.Equals, join.getQual().getType());
-  }
-
-  @Test
-  public final void testRightJoinClause() throws SQLSyntaxError {
-    Expr expr = analyzer.parse(JOINS[8]);
-
-    Join join = commonJoinTest(expr);
-    assertEquals(JoinType.RIGHT_OUTER, join.getJoinType());
-    Relation people = (Relation) join.getLeft();
-    assertEquals("people", people.getName());
-    assertEquals("p", people.getAlias());
-    Relation student = (Relation) join.getRight();
-    assertEquals("student", student.getName());
-    assertEquals("s", student.getAlias());
-    assertTrue(join.hasQual());
-    assertEquals(ExprType.Equals, join.getQual().getType());
-  }
-
-  private final String [] setClauses = {
-      "select id, people_id from student union select id, people_id from branch",
-      "select id, people_id from student union select id, people_id from branch " +
-          "intersect select id, people_id from branch as b"
-  };
-
-  @Test
-  public final void testUnionClause() throws SQLSyntaxError {
-    Expr expr = analyzer.parse(setClauses[0]);
-    assertEquals(ExprType.Union, expr.getType());
-    SetOperation union = (SetOperation) expr;
-    Expr left = union.getLeft();
-    Expr right = union.getRight();
-
-    assertEquals(ExprType.Projection, left.getType());
-    Projection leftProj = (Projection) left;
-    Relation student = (Relation) leftProj.getChild();
-
-    assertEquals(ExprType.Projection, right.getType());
-    Projection rightProj = (Projection) right;
-    Relation branch = (Relation) rightProj.getChild();
-
-    assertEquals("student", student.getName());
-    assertEquals("branch", branch.getName());
-
-    // multiple set statements
-    expr = analyzer.parse(setClauses[1]);
-    assertEquals(ExprType.Union, expr.getType());
-    union = (SetOperation) expr;
-
-    assertEquals(ExprType.Projection, union.getLeft().getType());
-    assertEquals(ExprType.Intersect, union.getRight().getType());
-    leftProj = (Projection) union.getLeft();
-    student = (Relation) leftProj.getChild();
-    assertEquals("student", student.getName());
-
-    SetOperation intersect = (SetOperation) union.getRight();
-    Relation branch2 = (Relation) ((Projection)intersect.getLeft()).getChild();
-    Relation branch3 = (Relation) ((Projection)intersect.getRight()).getChild();
-    assertEquals("branch", branch2.getName());
-    assertFalse(branch2.hasAlias());
-    assertEquals("branch", branch3.getName());
-    assertEquals("b", branch3.getAlias());
-  }
-
-  @Test
-  public void testCaseWhen() throws SQLSyntaxError {
-    Expr tree = analyzer.parse(
-        "select case when p_type like 'PROMO%' then l_extendedprice * (1 - l_discount) " +
-          "when p_type = 'MOCC' then l_extendedprice - 100 else 0 end as cond from lineitem, part");
-
-    assertEquals(ExprType.Projection, tree.getType());
-    Projection projection = (Projection) tree;
-    assertTrue(projection.getTargets()[0].hasAlias());
-    assertEquals(ExprType.CaseWhen, projection.getTargets()[0].getExpr().getType());
-    assertEquals("cond", projection.getTargets()[0].getAlias());
-    CaseWhenExpr caseWhen = (CaseWhenExpr) projection.getTargets()[0].getExpr();
-    assertEquals(2, caseWhen.getWhens().size());
-  }
-
-  public static String [] subQueries = {
-      "select c1, c2, c3 from (select c1, c2, c3 from employee) as test",
-      "select c1, c2, c3 from table1 where c3 < (select c4 from table2)"
-  };
-
-  @Test
-  public void testTableSubQuery() throws SQLSyntaxError {
-    Expr expr = analyzer.parse(subQueries[0]);
-    assertEquals(ExprType.Projection, expr.getType());
-    Projection projection = (Projection) expr;
-    assertEquals(ExprType.TableSubQuery, projection.getChild().getType());
-  }
-
-  @Test
-  public void testScalarSubQuery() throws SQLSyntaxError {
-    Expr expr = analyzer.parse(subQueries[1]);
-    assertEquals(ExprType.Projection, expr.getType());
-    Projection projection = (Projection) expr;
-    assertEquals(ExprType.Selection, projection.getChild().getType());
-  }
-
-  static final String [] setQualifier = {
-      "select id, people_id from student",
-      "select distinct id, people_id from student",
-      "select all id, people_id from student",
-  };
-
-  @Test
-  public final void testSetQulaifier() throws SQLSyntaxError {
-    Expr expr = analyzer.parse(setQualifier[0]);
-    assertEquals(ExprType.Projection, expr.getType());
-    Projection projection = (Projection) expr;
-    assertFalse(projection.isDistinct());
-
-    expr = analyzer.parse(setQualifier[1]);
-    assertEquals(ExprType.Projection, expr.getType());
-    projection = (Projection) expr;
-    assertTrue(projection.isDistinct());
-
-    expr = analyzer.parse(setQualifier[2]);
-    assertEquals(ExprType.Projection, expr.getType());
-    projection = (Projection) expr;
-    assertFalse(projection.isDistinct());
-  }
-
-  static final String [] createTableStmts = {
-      "create table table1 (name varchar, age int)",
-      "create table table1 (name string, age int) using rcfile",
-      "create table table1 (name string, age int) using rcfile with ('rcfile.buffer' = 4096)",
-      // create table test
-      "create table store1 as select name, score from people order by score asc, age desc null first",// 0
-      // create table test
-      "create table store1 (c1 string, c2 long) as select name, score from people order by score asc, age desc null first",// 1
-      // create table test
-      "create table store2 using rcfile with ('rcfile.buffer' = 4096) as select name, score from people order by score asc, age desc null first", // 2
-      // create table def
-      "create table table1 (name string, age int, earn long, score float) using rcfile with ('rcfile.buffer' = 4096)", // 4
-      // create table def with location
-      "create external table table1 (name string, age int, earn long, score float) using csv with ('csv.delimiter'='|') location '/tmp/data'" // 5
-  };
-
-  @Test
-  public final void testCreateTable1() throws SQLSyntaxError {
-    CreateTable stmt = (CreateTable) analyzer.parse(createTableStmts[0]);
-    assertEquals("table1", stmt.getRelationName());
-    assertTrue(stmt.hasTableElements());
-
-    stmt = (CreateTable) analyzer.parse(createTableStmts[1]);
-    assertEquals("table1", stmt.getRelationName());
-    assertTrue(stmt.hasTableElements());
-    assertTrue(stmt.hasStorageType());
-    assertEquals("rcfile", stmt.getStorageType());
-
-    stmt = (CreateTable) analyzer.parse(createTableStmts[2]);
-    assertEquals("table1", stmt.getRelationName());
-    assertTrue(stmt.hasTableElements());
-    assertTrue(stmt.hasStorageType());
-    assertEquals("rcfile", stmt.getStorageType());
-    assertTrue(stmt.hasParams());
-    assertEquals("4096", stmt.getParams().get("rcfile.buffer"));
-  }
-
-  @Test
-  public final void testCreateTableAsSelect() throws SQLSyntaxError {
-    CreateTable stmt = (CreateTable) analyzer.parse(createTableStmts[3]);
-    assertEquals("store1", stmt.getRelationName());
-    assertTrue(stmt.hasSubQuery());
-    testOrderByCluse(stmt.getSubQuery());
-
-    stmt = (CreateTable) analyzer.parse(createTableStmts[4]);
-    assertEquals("store1", stmt.getRelationName());
-    assertTrue(stmt.hasSubQuery());
-    testOrderByCluse(stmt.getSubQuery());
-    assertTrue(stmt.hasTableElements());
-
-    stmt = (CreateTable) analyzer.parse(createTableStmts[5]);
-    assertEquals("store2", stmt.getRelationName());
-    assertEquals("rcfile", stmt.getStorageType());
-    assertEquals("4096", stmt.getParams().get("rcfile.buffer"));
-    testOrderByCluse(stmt.getSubQuery());
-  }
-
-  private static void testOrderByCluse(Expr block) {
-    Projection projection = (Projection) block;
-    Sort sort = (Sort) projection.getChild();
-
-    assertEquals(2, sort.getSortSpecs().length);
-    Sort.SortSpec spec1 = sort.getSortSpecs()[0];
-    assertEquals("score", spec1.getKey().getName());
-    assertEquals(true, spec1.isAscending());
-    assertEquals(false, spec1.isNullFirst());
-    Sort.SortSpec spec2 = sort.getSortSpecs()[1];
-    assertEquals("age", spec2.getKey().getName());
-    assertEquals(false, spec2.isAscending());
-    assertEquals(true, spec2.isNullFirst());
-  }
-
-  @Test
-  public final void testCreateTableDef1() throws SQLSyntaxError {
-    CreateTable stmt = (CreateTable) analyzer.parse(createTableStmts[6]);
-    assertEquals("table1", stmt.getRelationName());
-    CreateTable.ColumnDefinition[] elements = stmt.getTableElements();
-    assertEquals("name", elements[0].getColumnName());
-    assertEquals("string", elements[0].getDataType());
-    assertEquals("age", elements[1].getColumnName());
-    assertEquals("int", elements[1].getDataType());
-    assertEquals("earn", elements[2].getColumnName());
-    assertEquals("long", elements[2].getDataType());
-    assertEquals("score", elements[3].getColumnName());
-    assertEquals("float", elements[3].getDataType());
-    assertEquals("rcfile", stmt.getStorageType());
-    assertFalse(stmt.hasLocation());
-    assertTrue(stmt.hasParams());
-    assertEquals("4096", stmt.getParams().get("rcfile.buffer"));
-  }
-
-  @Test
-  public final void testCreateTableDef2() throws SQLSyntaxError {
-    CreateTable expr = (CreateTable) analyzer.parse(createTableStmts[7]);
-    _testCreateTableDef2(expr);
-    CreateTable restored = (CreateTable) AlgebraTestingUtil.testJsonSerializer(expr);
-    _testCreateTableDef2(restored);
-  }
-
-  private void _testCreateTableDef2(CreateTable expr) {
-    assertEquals("table1", expr.getRelationName());
-    CreateTable.ColumnDefinition[] elements = expr.getTableElements();
-    assertEquals("name", elements[0].getColumnName());
-    assertEquals("string", elements[0].getDataType());
-    assertEquals("age", elements[1].getColumnName());
-    assertEquals("int", elements[1].getDataType());
-    assertEquals("earn", elements[2].getColumnName());
-    assertEquals("long", elements[2].getDataType());
-    assertEquals("score", elements[3].getColumnName());
-    assertEquals("float", elements[3].getDataType());
-    assertEquals("csv", expr.getStorageType());
-    assertEquals("/tmp/data", expr.getLocation());
-    assertTrue(expr.hasParams());
-    assertEquals("|", expr.getParams().get("csv.delimiter"));
-  }
-}