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 2014/08/20 08:05:09 UTC

git commit: TAJO-1013: a complex equality condition including columns of the same table is recognized as a join condition.

Repository: tajo
Updated Branches:
  refs/heads/master 49d52553c -> 7c84aeb29


TAJO-1013: a complex equality condition including columns of the same table is recognized as a join condition.

Closes #123


Project: http://git-wip-us.apache.org/repos/asf/tajo/repo
Commit: http://git-wip-us.apache.org/repos/asf/tajo/commit/7c84aeb2
Tree: http://git-wip-us.apache.org/repos/asf/tajo/tree/7c84aeb2
Diff: http://git-wip-us.apache.org/repos/asf/tajo/diff/7c84aeb2

Branch: refs/heads/master
Commit: 7c84aeb298919ac0e6a1eb1c469ae830656f17fa
Parents: 49d5255
Author: Hyunsik Choi <hy...@apache.org>
Authored: Wed Aug 20 15:03:35 2014 +0900
Committer: Hyunsik Choi <hy...@apache.org>
Committed: Wed Aug 20 15:04:39 2014 +0900

----------------------------------------------------------------------
 CHANGES                                         |   6 +-
 .../apache/tajo/engine/eval/EvalTreeUtil.java   | 100 +++++++++++++------
 .../apache/tajo/engine/planner/ExprFinder.java  |   2 +-
 .../engine/planner/LogicalPlanPreprocessor.java |  22 ++--
 .../engine/planner/logical/join/JoinGraph.java  |   2 +-
 .../planner/rewrite/FilterPushDownRule.java     |  19 ++--
 .../tajo/engine/eval/TestEvalTreeUtil.java      |   7 ++
 .../tajo/engine/query/TestSelectQuery.java      |  14 +++
 .../testColumnEqualityButNotJoinCondition1.sql  |   7 ++
 .../testColumnEqualityButNotJoinCondition2.sql  |   7 ++
 ...estColumnEqualityButNotJoinCondition1.result |   3 +
 ...estColumnEqualityButNotJoinCondition2.result |   6 ++
 12 files changed, 149 insertions(+), 46 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tajo/blob/7c84aeb2/CHANGES
----------------------------------------------------------------------
diff --git a/CHANGES b/CHANGES
index 96ffa4a..9a22e27 100644
--- a/CHANGES
+++ b/CHANGES
@@ -120,7 +120,11 @@ Release 0.9.0 - unreleased
 
   BUG FIXES
 
-    TAJO-1011: EvalTreeUtil::isJoinQual need to handle other join conditions. (jaehwa)
+    TAJO-1013: A complex equality condition including columns of the same
+    table is recognized as a join condition. (hyunsik)
+
+    TAJO-1011: EvalTreeUtil::isJoinQual need to handle other join conditions.
+    (jaehwa)
 
     TAJO-1009: A binary eval for column references of the same tables 
     should not be recognized as a join condition. (hyunsik)

http://git-wip-us.apache.org/repos/asf/tajo/blob/7c84aeb2/tajo-core/src/main/java/org/apache/tajo/engine/eval/EvalTreeUtil.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/eval/EvalTreeUtil.java b/tajo-core/src/main/java/org/apache/tajo/engine/eval/EvalTreeUtil.java
index 607383f..3e7a05b 100644
--- a/tajo-core/src/main/java/org/apache/tajo/engine/eval/EvalTreeUtil.java
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/eval/EvalTreeUtil.java
@@ -20,11 +20,17 @@ package org.apache.tajo.engine.eval;
 
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
+import org.apache.tajo.algebra.ColumnReferenceExpr;
+import org.apache.tajo.algebra.NamedExpr;
+import org.apache.tajo.algebra.OpType;
+import org.apache.tajo.annotation.Nullable;
 import org.apache.tajo.catalog.CatalogUtil;
 import org.apache.tajo.catalog.Column;
 import org.apache.tajo.catalog.Schema;
 import org.apache.tajo.common.TajoDataTypes.DataType;
 import org.apache.tajo.datum.Datum;
+import org.apache.tajo.engine.planner.ExprFinder;
+import org.apache.tajo.engine.planner.LogicalPlan;
 import org.apache.tajo.engine.planner.Target;
 import org.apache.tajo.exception.InternalException;
 import org.apache.tajo.util.TUtil;
@@ -250,6 +256,29 @@ public class EvalTreeUtil {
    * @return True if it is join condition.
    */
   public static boolean isJoinQual(EvalNode expr, boolean includeThetaJoin) {
+    return isJoinQual(null, expr, includeThetaJoin);
+  }
+
+  /**
+   * If a given expression is join condition, it returns TRUE. Otherwise, it returns FALSE.
+   *
+   * If three conditions are satisfied, we can recognize the expression as a equi join condition.
+   * <ol>
+   *   <li>An expression is an equal comparison expression.</li>
+   *   <li>Both terms in an expression are column references.</li>
+   *   <li>Both column references point come from different tables</li>
+   * </ol>
+   *
+   * For theta join condition, we will use "an expression is a predicate including column references which come
+   * from different two tables" instead of the first rule.
+   *
+   * @param block if block is not null, it tracks the lineage of aliased name derived from complex expressions.
+   * @param expr EvalNode to be evaluated
+   * @param includeThetaJoin If true, it will return equi as well as non-equi join conditions.
+   *                         Otherwise, it only returns equi-join conditions.
+   * @return True if it is join condition.
+   */
+  public static boolean isJoinQual(@Nullable LogicalPlan.QueryBlock block, EvalNode expr, boolean includeThetaJoin) {
 
     if (expr instanceof BinaryEval) {
       boolean joinComparator;
@@ -262,38 +291,53 @@ public class EvalTreeUtil {
       BinaryEval binaryEval = (BinaryEval) expr;
       boolean isBothTermFields = isSingleColumn(binaryEval.getLeftExpr()) && isSingleColumn(binaryEval.getRightExpr());
 
-      // If there is a filter using constants, we can't find unique column name as follows:
-      // ex) select * from lineitem where l_orderkey = 2;
-      // In this case, we may find NoSuchElementException because iterator has not any elements.
-      // Thus, we should find whether iterator has one more elements.
-      String leftQualifier = "", rightQualifier = "";
-      if (EvalTreeUtil.findUniqueColumns(binaryEval.getLeftExpr()).iterator().hasNext()) {
-        Column leftColumn = EvalTreeUtil.findUniqueColumns(binaryEval.getLeftExpr()).iterator().next();
-        leftQualifier = leftColumn.getQualifiedName();
-      }
+      Set<Column> leftColumns = EvalTreeUtil.findUniqueColumns(binaryEval.getLeftExpr());
+      Set<Column> rightColumns = EvalTreeUtil.findUniqueColumns(binaryEval.getRightExpr());
 
-      if (EvalTreeUtil.findUniqueColumns(binaryEval.getRightExpr()).iterator().hasNext()) {
-        Column rightColumn = EvalTreeUtil.findUniqueColumns(binaryEval.getRightExpr()).iterator().next();
-        rightQualifier = rightColumn.getQualifiedName();
-      }
+      boolean ensureColumnsOfDifferentTables = false;
 
-      String extractLeftQualifier = CatalogUtil.extractQualifier(leftQualifier);
-      String extractRightQualifier = CatalogUtil.extractQualifier(rightQualifier);
-      boolean isDifferentTables = false;
-
-      // If there are column alias and some functions, extracted qualifier will be empty data as follows:
-      // ex) select   n1.n_nationkey,   substr(n1.n_name, 1, 4) name1,   substr(n2.n_name, 1, 4) name2
-      //     from nation n1 join nation n2 on substr(n1.n_name, 1, 4) = substr(n2.n_name, 1, 4)
-      //     order by n1.n_nationkey;
-      // Thus, we can't check whether join tables used different tables.
-      if (extractLeftQualifier.equals("") && extractRightQualifier.equals("")) {
-        isDifferentTables = true;
-      } else {
-        isDifferentTables = !(CatalogUtil.extractQualifier(leftQualifier).
-            equals(CatalogUtil.extractQualifier(rightQualifier)));
+      if (leftColumns.size() == 1 && rightColumns.size() == 1) { // ensure there is only one column of each table
+        Column leftColumn = leftColumns.iterator().next();
+        Column rightColumn = rightColumns.iterator().next();
+
+        String leftQualifier = CatalogUtil.extractQualifier(leftColumn.getQualifiedName());
+        String rightQualifier = CatalogUtil.extractQualifier(rightColumn.getQualifiedName());
+
+        // if block is given, it will track an original expression of each term in order to decide whether
+        // this expression is a join condition, or not.
+        if (block != null) {
+          boolean leftQualified = CatalogUtil.isFQColumnName(leftColumn.getQualifiedName());
+          boolean rightQualified = CatalogUtil.isFQColumnName(rightColumn.getQualifiedName());
+
+          if (!leftQualified) { // if left one is aliased name
+
+            // getting original expression of left term
+            NamedExpr rawExpr = block.getNamedExprsManager().getNamedExpr(leftColumn.getQualifiedName());
+            Set<ColumnReferenceExpr> foundColumns = ExprFinder.finds(rawExpr.getExpr(), OpType.Column);
+
+            // ensure there is only one column of an original expression
+            if (foundColumns.size() == 1) {
+              leftQualifier = CatalogUtil.extractQualifier(foundColumns.iterator().next().getCanonicalName());
+            }
+          }
+          if (!rightQualified) { // if right one is aliased name
+
+            // getting original expression of right term
+            NamedExpr rawExpr = block.getNamedExprsManager().getNamedExpr(rightColumn.getQualifiedName());
+            Set<ColumnReferenceExpr> foundColumns = ExprFinder.finds(rawExpr.getExpr(), OpType.Column);
+
+            // ensure there is only one column of an original expression
+            if (foundColumns.size() == 1) {
+              rightQualifier = CatalogUtil.extractQualifier(foundColumns.iterator().next().getCanonicalName());
+            }
+          }
+        }
+
+        // if columns of both term is different to each other, it will be true.
+        ensureColumnsOfDifferentTables = !leftQualifier.equals(rightQualifier);
       }
 
-      return joinComparator && isBothTermFields && isDifferentTables;
+      return joinComparator && isBothTermFields && ensureColumnsOfDifferentTables;
     } else {
       return false;
     }

http://git-wip-us.apache.org/repos/asf/tajo/blob/7c84aeb2/tajo-core/src/main/java/org/apache/tajo/engine/planner/ExprFinder.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/planner/ExprFinder.java b/tajo-core/src/main/java/org/apache/tajo/engine/planner/ExprFinder.java
index 89eed91..dbc844d 100644
--- a/tajo-core/src/main/java/org/apache/tajo/engine/planner/ExprFinder.java
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/planner/ExprFinder.java
@@ -27,7 +27,7 @@ import java.util.HashSet;
 import java.util.Set;
 import java.util.Stack;
 
-class ExprFinder extends SimpleAlgebraVisitor<ExprFinder.Context, Object> {
+public class ExprFinder extends SimpleAlgebraVisitor<ExprFinder.Context, Object> {
 
   static class Context {
     Set<Expr> set = new HashSet<Expr>();

http://git-wip-us.apache.org/repos/asf/tajo/blob/7c84aeb2/tajo-core/src/main/java/org/apache/tajo/engine/planner/LogicalPlanPreprocessor.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/planner/LogicalPlanPreprocessor.java b/tajo-core/src/main/java/org/apache/tajo/engine/planner/LogicalPlanPreprocessor.java
index 674525c..96758d6 100644
--- a/tajo-core/src/main/java/org/apache/tajo/engine/planner/LogicalPlanPreprocessor.java
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/planner/LogicalPlanPreprocessor.java
@@ -29,7 +29,6 @@ import org.apache.tajo.engine.planner.LogicalPlan.QueryBlock;
 import org.apache.tajo.engine.planner.logical.*;
 import org.apache.tajo.engine.planner.nameresolver.NameResolver;
 import org.apache.tajo.engine.planner.nameresolver.NameResolvingMode;
-import org.apache.tajo.engine.query.QueryContext;
 import org.apache.tajo.engine.utils.SchemaUtil;
 import org.apache.tajo.util.TUtil;
 
@@ -183,14 +182,14 @@ public class LogicalPlanPreprocessor extends BaseAlgebraVisitor<LogicalPlanner.P
       expr.setNamedExprs(rewrittenTargets.toArray(new NamedExpr[rewrittenTargets.size()]));
     }
 
-    // 1) Normalize field names into full qualified names
-    // 2) Register explicit column aliases to block
     NamedExpr[] projectTargetExprs = expr.getNamedExprs();
-    NameRefInSelectListNormalizer normalizer = new NameRefInSelectListNormalizer();
     for (int i = 0; i < expr.getNamedExprs().length; i++) {
       NamedExpr namedExpr = projectTargetExprs[i];
-      normalizer.visit(ctx, new Stack<Expr>(), namedExpr.getExpr());
 
+      // 1) Normalize all field names occured in each expr into full qualified names
+      NameRefInSelectListNormalizer.normalize(ctx, namedExpr.getExpr());
+
+      // 2) Register explicit column aliases to block
       if (namedExpr.getExpr().getType() == OpType.Column && namedExpr.hasAlias()) {
         ctx.queryBlock.addColumnAlias(((ColumnReferenceExpr)namedExpr.getExpr()).getCanonicalName(),
             namedExpr.getAlias());
@@ -461,7 +460,18 @@ public class LogicalPlanPreprocessor extends BaseAlgebraVisitor<LogicalPlanner.P
     return insertNode;
   }
 
-  class NameRefInSelectListNormalizer extends SimpleAlgebraVisitor<LogicalPlanner.PlanContext, Object> {
+  static class NameRefInSelectListNormalizer extends SimpleAlgebraVisitor<LogicalPlanner.PlanContext, Object> {
+    private static final NameRefInSelectListNormalizer instance;
+
+    static {
+      instance = new NameRefInSelectListNormalizer();
+    }
+
+    public static void normalize(LogicalPlanner.PlanContext context, Expr expr) throws PlanningException {
+      NameRefInSelectListNormalizer normalizer = new NameRefInSelectListNormalizer();
+      normalizer.visit(context,new Stack<Expr>(), expr);
+    }
+
     @Override
     public Expr visitColumnReference(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, ColumnReferenceExpr expr)
         throws PlanningException {

http://git-wip-us.apache.org/repos/asf/tajo/blob/7c84aeb2/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/join/JoinGraph.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/join/JoinGraph.java b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/join/JoinGraph.java
index 6390a77..776e776 100644
--- a/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/join/JoinGraph.java
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/planner/logical/join/JoinGraph.java
@@ -120,7 +120,7 @@ public class JoinGraph extends SimpleUndirectedGraph<String, JoinEdge> {
       Set<EvalNode> cnf = Sets.newHashSet(AlgebraicUtil.toConjunctiveNormalFormArray(joinNode.getJoinQual()));
 
       for (EvalNode singleQual : cnf) {
-        if (EvalTreeUtil.isJoinQual(singleQual, true)) {
+        if (EvalTreeUtil.isJoinQual(block, singleQual, true)) {
           String[] relations = guessRelationsFromJoinQual(block, (BinaryEval) singleQual);
           String leftExprRelName = relations[0];
           String rightExprRelName = relations[1];

http://git-wip-us.apache.org/repos/asf/tajo/blob/7c84aeb2/tajo-core/src/main/java/org/apache/tajo/engine/planner/rewrite/FilterPushDownRule.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/planner/rewrite/FilterPushDownRule.java b/tajo-core/src/main/java/org/apache/tajo/engine/planner/rewrite/FilterPushDownRule.java
index 34c88a6..b5dafcb 100644
--- a/tajo-core/src/main/java/org/apache/tajo/engine/planner/rewrite/FilterPushDownRule.java
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/planner/rewrite/FilterPushDownRule.java
@@ -236,7 +236,7 @@ public class FilterPushDownRule extends BasicLogicalPlanVisitor<FilterPushDownCo
 
       List<EvalNode> removedFromFilter = new ArrayList<EvalNode>();
       for (EvalNode eachEval: context.pushingDownFilters) {
-        if (EvalTreeUtil.isJoinQual(eachEval, true)) {
+        if (EvalTreeUtil.isJoinQual(block, eachEval, true)) {
           outerJoinPredicationEvals.add(eachEval);
           removedFromFilter.add(eachEval);
         } else {
@@ -287,8 +287,8 @@ public class FilterPushDownRule extends BasicLogicalPlanVisitor<FilterPushDownCo
 
     List<EvalNode> notMatched = new ArrayList<EvalNode>();
     // Join's input schema = right child output columns + left child output columns
-    Map<EvalNode, EvalNode> transformedMap = findCanPushdownAndTransform(context, joinNode, left, notMatched, null, true,
-        0);
+    Map<EvalNode, EvalNode> transformedMap = findCanPushdownAndTransform(context, block, joinNode, left, notMatched,
+        null, true, 0);
     context.setFiltersTobePushed(transformedMap.keySet());
     visit(context, plan, block, left, stack);
 
@@ -296,7 +296,8 @@ public class FilterPushDownRule extends BasicLogicalPlanVisitor<FilterPushDownCo
     context.addFiltersTobePushed(notMatched);
 
     notMatched.clear();
-    transformedMap = findCanPushdownAndTransform(context, joinNode, right, notMatched, null, true, left.getOutSchema().size());
+    transformedMap = findCanPushdownAndTransform(context, block, joinNode, right, notMatched, null, true,
+        left.getOutSchema().size());
     context.setFiltersTobePushed(new HashSet<EvalNode>(transformedMap.keySet()));
 
     visit(context, plan, block, right, stack);
@@ -511,7 +512,7 @@ public class FilterPushDownRule extends BasicLogicalPlanVisitor<FilterPushDownCo
 
     //copy -> origin
     BiMap<EvalNode, EvalNode> transformedMap = findCanPushdownAndTransform(
-        context, projectionNode, childNode, notMatched, null, false, 0);
+        context, block,projectionNode, childNode, notMatched, null, false, 0);
 
     context.setFiltersTobePushed(transformedMap.keySet());
 
@@ -567,7 +568,7 @@ public class FilterPushDownRule extends BasicLogicalPlanVisitor<FilterPushDownCo
   }
 
   private BiMap<EvalNode, EvalNode> findCanPushdownAndTransform(
-      FilterPushDownContext context, Projectable node,
+      FilterPushDownContext context, LogicalPlan.QueryBlock block, Projectable node,
       LogicalNode childNode, List<EvalNode> notMatched,
       Set<String> partitionColumns,
       boolean ignoreJoin, int columnOffset) throws PlanningException {
@@ -581,7 +582,7 @@ public class FilterPushDownRule extends BasicLogicalPlanVisitor<FilterPushDownCo
     BiMap<EvalNode, EvalNode> matched = HashBiMap.create();
 
     for (EvalNode eval : context.pushingDownFilters) {
-      if (ignoreJoin && EvalTreeUtil.isJoinQual(eval, true)) {
+      if (ignoreJoin && EvalTreeUtil.isJoinQual(block, eval, true)) {
         notMatched.add(eval);
         continue;
       }
@@ -797,7 +798,7 @@ public class FilterPushDownRule extends BasicLogicalPlanVisitor<FilterPushDownCo
     List<EvalNode> notMatched = new ArrayList<EvalNode>();
     // transform
     Map<EvalNode, EvalNode> tranformed =
-        findCanPushdownAndTransform(context, groupbyNode,groupbyNode.getChild(), notMatched, null, false, 0);
+        findCanPushdownAndTransform(context, block, groupbyNode,groupbyNode.getChild(), notMatched, null, false, 0);
 
     context.setFiltersTobePushed(tranformed.keySet());
     LogicalNode current = super.visitGroupBy(context, plan, block, groupbyNode, stack);
@@ -862,7 +863,7 @@ public class FilterPushDownRule extends BasicLogicalPlanVisitor<FilterPushDownCo
 
     // transform
     Map<EvalNode, EvalNode> transformed =
-        findCanPushdownAndTransform(context, scanNode, null, notMatched, partitionColumns, true, 0);
+        findCanPushdownAndTransform(context, block, scanNode, null, notMatched, partitionColumns, true, 0);
 
     for (EvalNode eval : transformed.keySet()) {
       if (LogicalPlanner.checkIfBeEvaluatedAtRelation(block, eval, scanNode)) {

http://git-wip-us.apache.org/repos/asf/tajo/blob/7c84aeb2/tajo-core/src/test/java/org/apache/tajo/engine/eval/TestEvalTreeUtil.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/test/java/org/apache/tajo/engine/eval/TestEvalTreeUtil.java b/tajo-core/src/test/java/org/apache/tajo/engine/eval/TestEvalTreeUtil.java
index 9000c18..50fd66d 100644
--- a/tajo-core/src/test/java/org/apache/tajo/engine/eval/TestEvalTreeUtil.java
+++ b/tajo-core/src/test/java/org/apache/tajo/engine/eval/TestEvalTreeUtil.java
@@ -372,4 +372,11 @@ public class TestEvalTreeUtil {
     EvalNode evalNode = getRootSelection("select score from people where people.score > people.age");
     assertFalse(EvalTreeUtil.isJoinQual(evalNode, true));
   }
+
+  @Test
+  public final void testIsJoinQual2() throws PlanningException {
+    EvalNode evalNode = getRootSelection(
+        "select score from people where substr(people.score::text,1,1) > substr(people.age::text,1,1)");
+    assertFalse(EvalTreeUtil.isJoinQual(evalNode, true));
+  }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/7c84aeb2/tajo-core/src/test/java/org/apache/tajo/engine/query/TestSelectQuery.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/test/java/org/apache/tajo/engine/query/TestSelectQuery.java b/tajo-core/src/test/java/org/apache/tajo/engine/query/TestSelectQuery.java
index 09c8bf3..17ce37b 100644
--- a/tajo-core/src/test/java/org/apache/tajo/engine/query/TestSelectQuery.java
+++ b/tajo-core/src/test/java/org/apache/tajo/engine/query/TestSelectQuery.java
@@ -509,4 +509,18 @@ public class TestSelectQuery extends QueryTestCaseBase {
     assertResultSet(res);
     cleanupQuery(res);
   }
+
+  @Test
+  public void testColumnEqualityButNotJoinCondition1() throws Exception {
+    ResultSet res = executeQuery();
+    assertResultSet(res);
+    cleanupQuery(res);
+  }
+
+  @Test
+  public void testColumnEqualityButNotJoinCondition2() throws Exception {
+    ResultSet res = executeQuery();
+    assertResultSet(res);
+    cleanupQuery(res);
+  }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/7c84aeb2/tajo-core/src/test/resources/queries/TestSelectQuery/testColumnEqualityButNotJoinCondition1.sql
----------------------------------------------------------------------
diff --git a/tajo-core/src/test/resources/queries/TestSelectQuery/testColumnEqualityButNotJoinCondition1.sql b/tajo-core/src/test/resources/queries/TestSelectQuery/testColumnEqualityButNotJoinCondition1.sql
new file mode 100644
index 0000000..f47d21c
--- /dev/null
+++ b/tajo-core/src/test/resources/queries/TestSelectQuery/testColumnEqualityButNotJoinCondition1.sql
@@ -0,0 +1,7 @@
+SELECT
+  L_ORDERKEY,
+  L_PARTKEY
+FROM
+  LINEITEM
+WHERE
+  L_ORDERKEY > L_PARTKEY;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/7c84aeb2/tajo-core/src/test/resources/queries/TestSelectQuery/testColumnEqualityButNotJoinCondition2.sql
----------------------------------------------------------------------
diff --git a/tajo-core/src/test/resources/queries/TestSelectQuery/testColumnEqualityButNotJoinCondition2.sql b/tajo-core/src/test/resources/queries/TestSelectQuery/testColumnEqualityButNotJoinCondition2.sql
new file mode 100644
index 0000000..dd153d5
--- /dev/null
+++ b/tajo-core/src/test/resources/queries/TestSelectQuery/testColumnEqualityButNotJoinCondition2.sql
@@ -0,0 +1,7 @@
+SELECT
+  SUBSTR(L_ORDERKEY::TEXT,1,1),
+  SUBSTR(L_PARTKEY::TEXT,1,1)
+  FROM
+      LINEITEM
+  WHERE
+  SUBSTR(L_ORDERKEY::TEXT,1,1) = SUBSTR(L_PARTKEY::TEXT,1,1);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/7c84aeb2/tajo-core/src/test/resources/results/TestSelectQuery/testColumnEqualityButNotJoinCondition1.result
----------------------------------------------------------------------
diff --git a/tajo-core/src/test/resources/results/TestSelectQuery/testColumnEqualityButNotJoinCondition1.result b/tajo-core/src/test/resources/results/TestSelectQuery/testColumnEqualityButNotJoinCondition1.result
new file mode 100644
index 0000000..3021a30
--- /dev/null
+++ b/tajo-core/src/test/resources/results/TestSelectQuery/testColumnEqualityButNotJoinCondition1.result
@@ -0,0 +1,3 @@
+l_orderkey,l_partkey
+-------------------------------
+3,2
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/7c84aeb2/tajo-core/src/test/resources/results/TestSelectQuery/testColumnEqualityButNotJoinCondition2.result
----------------------------------------------------------------------
diff --git a/tajo-core/src/test/resources/results/TestSelectQuery/testColumnEqualityButNotJoinCondition2.result b/tajo-core/src/test/resources/results/TestSelectQuery/testColumnEqualityButNotJoinCondition2.result
new file mode 100644
index 0000000..2b25165
--- /dev/null
+++ b/tajo-core/src/test/resources/results/TestSelectQuery/testColumnEqualityButNotJoinCondition2.result
@@ -0,0 +1,6 @@
+?substr,?substr_1
+-------------------------------
+1,1
+1,1
+2,2
+3,3
\ No newline at end of file