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