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/13 06:47:32 UTC

[1/2] TAJO-895: ConstEval should not be included in target list of projectable nodes.

Repository: tajo
Updated Branches:
  refs/heads/master bb482d8ee -> 7e31a3201


http://git-wip-us.apache.org/repos/asf/tajo/blob/7e31a320/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 5528b21..09c8bf3 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
@@ -166,6 +166,15 @@ public class TestSelectQuery extends QueryTestCaseBase {
   }
 
   @Test
+  public final void testSelectSameConstantsWithDifferentAliases3() throws Exception {
+    // select l_orderkey, '20130819' as date1, '20130819', '20130819', '20130819'
+    // from lineitem where l_orderkey > -1;
+    ResultSet res = executeQuery();
+    assertResultSet(res);
+    cleanupQuery(res);
+  }
+
+  @Test
   public final void testSelectSameExprsWithDifferentAliases() throws Exception {
     // select l_orderkey, l_partkey + 1 as plus1, l_partkey + 1 as plus2 from lineitem where l_orderkey > -1;
     ResultSet res = executeQuery();
@@ -451,7 +460,7 @@ public class TestSelectQuery extends QueryTestCaseBase {
       while (res.next()) {
         String currentNowValue = res.getString(1);
         if (nowValue != null) {
-          assertTrue(nowValue.equals(currentNowValue));
+          assertTrue(nowValue + " is different to " + currentNowValue, nowValue.equals(currentNowValue));
         }
         nowValue = currentNowValue;
         numRecords++;

http://git-wip-us.apache.org/repos/asf/tajo/blob/7e31a320/tajo-core/src/test/java/org/apache/tajo/engine/query/TestSortQuery.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/test/java/org/apache/tajo/engine/query/TestSortQuery.java b/tajo-core/src/test/java/org/apache/tajo/engine/query/TestSortQuery.java
index c7f6406..7d2c5d2 100644
--- a/tajo-core/src/test/java/org/apache/tajo/engine/query/TestSortQuery.java
+++ b/tajo-core/src/test/java/org/apache/tajo/engine/query/TestSortQuery.java
@@ -218,4 +218,21 @@ public class TestSortQuery extends QueryTestCaseBase {
       executeString("DROP TABLE nullsort PURGE;").close();
     }
   }
+
+  @Test
+  public final void testSortWithConstKeys() throws Exception {
+    // select
+    //   l_orderkey,
+    //   l_linenumber,
+    //   1 as key1,
+    //   2 as key2
+    // from
+    //   lineitem
+    // order by
+    //   key1,
+    //  key2;
+    ResultSet res = executeQuery();
+    assertResultSet(res);
+    cleanupQuery(res);
+  }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/7e31a320/tajo-core/src/test/java/org/apache/tajo/engine/query/TestWindowQuery.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/test/java/org/apache/tajo/engine/query/TestWindowQuery.java b/tajo-core/src/test/java/org/apache/tajo/engine/query/TestWindowQuery.java
index d202153..d64dd20 100644
--- a/tajo-core/src/test/java/org/apache/tajo/engine/query/TestWindowQuery.java
+++ b/tajo-core/src/test/java/org/apache/tajo/engine/query/TestWindowQuery.java
@@ -83,6 +83,13 @@ public class TestWindowQuery extends QueryTestCaseBase {
   }
 
   @Test
+  public final void testWindow8() throws Exception {
+    ResultSet res = executeQuery();
+    assertResultSet(res);
+    cleanupQuery(res);
+  }
+
+  @Test
   public final void testWindowWithOrderBy1() throws Exception {
     ResultSet res = executeQuery();
     assertResultSet(res);

http://git-wip-us.apache.org/repos/asf/tajo/blob/7e31a320/tajo-core/src/test/resources/queries/TestGroupByQuery/testGroupByWithConstantKeys3.sql
----------------------------------------------------------------------
diff --git a/tajo-core/src/test/resources/queries/TestGroupByQuery/testGroupByWithConstantKeys3.sql b/tajo-core/src/test/resources/queries/TestGroupByQuery/testGroupByWithConstantKeys3.sql
new file mode 100644
index 0000000..568009d
--- /dev/null
+++ b/tajo-core/src/test/resources/queries/TestGroupByQuery/testGroupByWithConstantKeys3.sql
@@ -0,0 +1,8 @@
+select
+  timestamp '2014-07-07 04:28:31.561' as b,
+  '##' as c,
+  count(*) d
+from
+  lineitem
+group by
+  b, c;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/7e31a320/tajo-core/src/test/resources/queries/TestGroupByQuery/testGroupByWithConstantKeys4.sql
----------------------------------------------------------------------
diff --git a/tajo-core/src/test/resources/queries/TestGroupByQuery/testGroupByWithConstantKeys4.sql b/tajo-core/src/test/resources/queries/TestGroupByQuery/testGroupByWithConstantKeys4.sql
new file mode 100644
index 0000000..4de4dda
--- /dev/null
+++ b/tajo-core/src/test/resources/queries/TestGroupByQuery/testGroupByWithConstantKeys4.sql
@@ -0,0 +1,12 @@
+select
+  'day',
+  l_orderkey,
+  count(*) as sum
+from
+  lineitem
+group by
+  'day',
+  l_orderkey
+order by
+  'day',
+  l_orderkey;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/7e31a320/tajo-core/src/test/resources/queries/TestGroupByQuery/testGroupByWithConstantKeys5.sql
----------------------------------------------------------------------
diff --git a/tajo-core/src/test/resources/queries/TestGroupByQuery/testGroupByWithConstantKeys5.sql b/tajo-core/src/test/resources/queries/TestGroupByQuery/testGroupByWithConstantKeys5.sql
new file mode 100644
index 0000000..4132d37
--- /dev/null
+++ b/tajo-core/src/test/resources/queries/TestGroupByQuery/testGroupByWithConstantKeys5.sql
@@ -0,0 +1,13 @@
+select
+  'day',
+  'day' as key,
+  l_orderkey,
+  count(*) as sum
+from
+  lineitem
+group by
+  'day',
+  l_orderkey
+order by
+  'day',
+  l_orderkey;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/7e31a320/tajo-core/src/test/resources/queries/TestJoinQuery/testLeftOuterJoinWithConstantExpr4.sql
----------------------------------------------------------------------
diff --git a/tajo-core/src/test/resources/queries/TestJoinQuery/testLeftOuterJoinWithConstantExpr4.sql b/tajo-core/src/test/resources/queries/TestJoinQuery/testLeftOuterJoinWithConstantExpr4.sql
new file mode 100644
index 0000000..9e3838d
--- /dev/null
+++ b/tajo-core/src/test/resources/queries/TestJoinQuery/testLeftOuterJoinWithConstantExpr4.sql
@@ -0,0 +1,6 @@
+SELECT
+  l.l_orderkey,
+  o.o_orderkey,
+  '201405' as key1,
+  '5-LOW' as key2
+from lineitem l left outer join orders o on l.l_orderkey = o.o_orderkey and o_orderpriority = '5-LOW';

http://git-wip-us.apache.org/repos/asf/tajo/blob/7e31a320/tajo-core/src/test/resources/queries/TestJoinQuery/testLeftOuterJoinWithConstantExpr5.sql
----------------------------------------------------------------------
diff --git a/tajo-core/src/test/resources/queries/TestJoinQuery/testLeftOuterJoinWithConstantExpr5.sql b/tajo-core/src/test/resources/queries/TestJoinQuery/testLeftOuterJoinWithConstantExpr5.sql
new file mode 100644
index 0000000..720a004
--- /dev/null
+++ b/tajo-core/src/test/resources/queries/TestJoinQuery/testLeftOuterJoinWithConstantExpr5.sql
@@ -0,0 +1,9 @@
+SELECT
+  l.l_orderkey,
+  o.o_orderkey,
+  '201405' as key1,
+  '5-LOW' as key2
+from
+  lineitem l left outer join orders o on l.l_orderkey = o.o_orderkey
+WHERE
+  o_orderpriority = '5-LOW'

http://git-wip-us.apache.org/repos/asf/tajo/blob/7e31a320/tajo-core/src/test/resources/queries/TestSelectQuery/testSelectSameConstantsWithDifferentAliases3.sql
----------------------------------------------------------------------
diff --git a/tajo-core/src/test/resources/queries/TestSelectQuery/testSelectSameConstantsWithDifferentAliases3.sql b/tajo-core/src/test/resources/queries/TestSelectQuery/testSelectSameConstantsWithDifferentAliases3.sql
new file mode 100644
index 0000000..ec03a11
--- /dev/null
+++ b/tajo-core/src/test/resources/queries/TestSelectQuery/testSelectSameConstantsWithDifferentAliases3.sql
@@ -0,0 +1,10 @@
+select
+  l_orderkey,
+  '20130819' as date1,
+  '20130819',
+  '20130819',
+  '20130819'
+from
+  lineitem
+where
+  l_orderkey > -1;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/7e31a320/tajo-core/src/test/resources/queries/TestSortQuery/testSortWithConstKeys.sql
----------------------------------------------------------------------
diff --git a/tajo-core/src/test/resources/queries/TestSortQuery/testSortWithConstKeys.sql b/tajo-core/src/test/resources/queries/TestSortQuery/testSortWithConstKeys.sql
new file mode 100644
index 0000000..ddaf84f
--- /dev/null
+++ b/tajo-core/src/test/resources/queries/TestSortQuery/testSortWithConstKeys.sql
@@ -0,0 +1,10 @@
+select
+  l_orderkey,
+  l_linenumber,
+  1 as key1,
+  2 as key2
+from
+  lineitem
+order by
+  key1,
+  key2;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/7e31a320/tajo-core/src/test/resources/queries/TestWindowQuery/testWindow8.sql
----------------------------------------------------------------------
diff --git a/tajo-core/src/test/resources/queries/TestWindowQuery/testWindow8.sql b/tajo-core/src/test/resources/queries/TestWindowQuery/testWindow8.sql
new file mode 100644
index 0000000..4611bee
--- /dev/null
+++ b/tajo-core/src/test/resources/queries/TestWindowQuery/testWindow8.sql
@@ -0,0 +1,7 @@
+select
+  l_orderkey,
+  l_quantity,
+  rank() over (partition by l_orderkey) as r,
+  5 as const_val
+from
+  lineitem;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/7e31a320/tajo-core/src/test/resources/results/TestGroupByQuery/testGroupByWithConstantKeys3.result
----------------------------------------------------------------------
diff --git a/tajo-core/src/test/resources/results/TestGroupByQuery/testGroupByWithConstantKeys3.result b/tajo-core/src/test/resources/results/TestGroupByQuery/testGroupByWithConstantKeys3.result
new file mode 100644
index 0000000..3285621
--- /dev/null
+++ b/tajo-core/src/test/resources/results/TestGroupByQuery/testGroupByWithConstantKeys3.result
@@ -0,0 +1,3 @@
+b,c,d
+-------------------------------
+2014-07-07 04:28:31.561,##,5
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/7e31a320/tajo-core/src/test/resources/results/TestGroupByQuery/testGroupByWithConstantKeys4.result
----------------------------------------------------------------------
diff --git a/tajo-core/src/test/resources/results/TestGroupByQuery/testGroupByWithConstantKeys4.result b/tajo-core/src/test/resources/results/TestGroupByQuery/testGroupByWithConstantKeys4.result
new file mode 100644
index 0000000..69560d5
--- /dev/null
+++ b/tajo-core/src/test/resources/results/TestGroupByQuery/testGroupByWithConstantKeys4.result
@@ -0,0 +1,5 @@
+?text,l_orderkey,sum
+-------------------------------
+day,1,2
+day,2,1
+day,3,2
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/7e31a320/tajo-core/src/test/resources/results/TestGroupByQuery/testGroupByWithConstantKeys5.result
----------------------------------------------------------------------
diff --git a/tajo-core/src/test/resources/results/TestGroupByQuery/testGroupByWithConstantKeys5.result b/tajo-core/src/test/resources/results/TestGroupByQuery/testGroupByWithConstantKeys5.result
new file mode 100644
index 0000000..30ba1de
--- /dev/null
+++ b/tajo-core/src/test/resources/results/TestGroupByQuery/testGroupByWithConstantKeys5.result
@@ -0,0 +1,5 @@
+?text,key,l_orderkey,sum
+-------------------------------
+day,day,1,2
+day,day,2,1
+day,day,3,2
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/7e31a320/tajo-core/src/test/resources/results/TestJoinQuery/testLeftOuterJoinWithConstantExpr4.result
----------------------------------------------------------------------
diff --git a/tajo-core/src/test/resources/results/TestJoinQuery/testLeftOuterJoinWithConstantExpr4.result b/tajo-core/src/test/resources/results/TestJoinQuery/testLeftOuterJoinWithConstantExpr4.result
new file mode 100644
index 0000000..cb1c3fc
--- /dev/null
+++ b/tajo-core/src/test/resources/results/TestJoinQuery/testLeftOuterJoinWithConstantExpr4.result
@@ -0,0 +1,7 @@
+l_orderkey,o_orderkey,key1,key2
+-------------------------------
+1,1,201405,5-LOW
+1,1,201405,5-LOW
+2,null,201405,5-LOW
+3,3,201405,5-LOW
+3,3,201405,5-LOW
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/7e31a320/tajo-core/src/test/resources/results/TestJoinQuery/testLeftOuterJoinWithConstantExpr5.result
----------------------------------------------------------------------
diff --git a/tajo-core/src/test/resources/results/TestJoinQuery/testLeftOuterJoinWithConstantExpr5.result b/tajo-core/src/test/resources/results/TestJoinQuery/testLeftOuterJoinWithConstantExpr5.result
new file mode 100644
index 0000000..8ba8bba
--- /dev/null
+++ b/tajo-core/src/test/resources/results/TestJoinQuery/testLeftOuterJoinWithConstantExpr5.result
@@ -0,0 +1,6 @@
+l_orderkey,o_orderkey,key1,key2
+-------------------------------
+1,1,201405,5-LOW
+1,1,201405,5-LOW
+3,3,201405,5-LOW
+3,3,201405,5-LOW
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/7e31a320/tajo-core/src/test/resources/results/TestSelectQuery/testSelectAsterisk5.result
----------------------------------------------------------------------
diff --git a/tajo-core/src/test/resources/results/TestSelectQuery/testSelectAsterisk5.result b/tajo-core/src/test/resources/results/TestSelectQuery/testSelectAsterisk5.result
index 6fc2ceb..2eb0399 100644
--- a/tajo-core/src/test/resources/results/TestSelectQuery/testSelectAsterisk5.result
+++ b/tajo-core/src/test/resources/results/TestSelectQuery/testSelectAsterisk5.result
@@ -1,3 +1,3 @@
-l_orderkey,?literal
+l_orderkey,?number
 -------------------------------
 2,1
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/7e31a320/tajo-core/src/test/resources/results/TestSelectQuery/testSelectSameConstantsWithDifferentAliases3.result
----------------------------------------------------------------------
diff --git a/tajo-core/src/test/resources/results/TestSelectQuery/testSelectSameConstantsWithDifferentAliases3.result b/tajo-core/src/test/resources/results/TestSelectQuery/testSelectSameConstantsWithDifferentAliases3.result
new file mode 100644
index 0000000..909f4b9
--- /dev/null
+++ b/tajo-core/src/test/resources/results/TestSelectQuery/testSelectSameConstantsWithDifferentAliases3.result
@@ -0,0 +1,7 @@
+l_orderkey,date1,?text,?text_1,?text_2
+-------------------------------
+1,20130819,20130819,20130819,20130819
+1,20130819,20130819,20130819,20130819
+2,20130819,20130819,20130819,20130819
+3,20130819,20130819,20130819,20130819
+3,20130819,20130819,20130819,20130819
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/7e31a320/tajo-core/src/test/resources/results/TestSortQuery/testSortWithConstKeys.result
----------------------------------------------------------------------
diff --git a/tajo-core/src/test/resources/results/TestSortQuery/testSortWithConstKeys.result b/tajo-core/src/test/resources/results/TestSortQuery/testSortWithConstKeys.result
new file mode 100644
index 0000000..bfc709f
--- /dev/null
+++ b/tajo-core/src/test/resources/results/TestSortQuery/testSortWithConstKeys.result
@@ -0,0 +1,7 @@
+l_orderkey,l_linenumber,key1,key2
+-------------------------------
+1,1,1,2
+1,2,1,2
+2,1,1,2
+3,1,1,2
+3,2,1,2
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/7e31a320/tajo-core/src/test/resources/results/TestTajoCli/testLocalQueryWithoutFrom.result
----------------------------------------------------------------------
diff --git a/tajo-core/src/test/resources/results/TestTajoCli/testLocalQueryWithoutFrom.result b/tajo-core/src/test/resources/results/TestTajoCli/testLocalQueryWithoutFrom.result
index bf51d16..7d3718f 100644
--- a/tajo-core/src/test/resources/results/TestTajoCli/testLocalQueryWithoutFrom.result
+++ b/tajo-core/src/test/resources/results/TestTajoCli/testLocalQueryWithoutFrom.result
@@ -1,8 +1,8 @@
-?literal,  ?literal_1
+?text,  ?text_1
 -------------------------------
 abc,  123
 (1 rows, , 0 B selected)
 ?substr
 -------------------------------
 123
-(1 rows, , 0 B selected)
+(1 rows, , 0 B selected)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/7e31a320/tajo-core/src/test/resources/results/TestWindowQuery/testWindow8.result
----------------------------------------------------------------------
diff --git a/tajo-core/src/test/resources/results/TestWindowQuery/testWindow8.result b/tajo-core/src/test/resources/results/TestWindowQuery/testWindow8.result
new file mode 100644
index 0000000..f371de5
--- /dev/null
+++ b/tajo-core/src/test/resources/results/TestWindowQuery/testWindow8.result
@@ -0,0 +1,7 @@
+l_orderkey,l_quantity,r,const_val
+-------------------------------
+1,17.0,1,5
+1,36.0,1,5
+2,38.0,1,5
+3,45.0,1,5
+3,49.0,1,5
\ No newline at end of file


[2/2] git commit: TAJO-895: ConstEval should not be included in target list of projectable nodes.

Posted by hy...@apache.org.
TAJO-895: ConstEval should not be included in target list of projectable nodes.

Closes #111


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

Branch: refs/heads/master
Commit: 7e31a320144d2da6aae795f29d3bd9bbb16f9338
Parents: bb482d8
Author: Hyunsik Choi <hy...@apache.org>
Authored: Wed Aug 13 13:42:56 2014 +0900
Committer: Hyunsik Choi <hy...@apache.org>
Committed: Wed Aug 13 13:42:56 2014 +0900

----------------------------------------------------------------------
 CHANGES                                         |   3 +
 .../org/apache/tajo/engine/eval/BinaryEval.java |  14 +-
 .../apache/tajo/engine/eval/FunctionEval.java   |   6 +-
 .../eval/EvalTreeOptimizationRule.java          |  27 ++++
 .../optimizer/eval/EvalTreeOptimizer.java       |  76 +++++++++
 .../tajo/engine/optimizer/eval/Prioritized.java |  30 ++++
 .../optimizer/eval/rules/ConstantFolding.java   |  92 +++++++++++
 .../eval/rules/ConstantPropagation.java         | 112 ++++++++++++++
 .../tajo/engine/planner/ExprAnnotator.java      |  12 +-
 .../tajo/engine/planner/ExprNormalizer.java     |   2 +-
 .../apache/tajo/engine/planner/LogicalPlan.java |  56 ++++++-
 .../engine/planner/LogicalPlanPreprocessor.java | 120 +++++++--------
 .../tajo/engine/planner/LogicalPlanner.java     | 154 ++++++++++++-------
 .../tajo/engine/planner/NamedExprsManager.java  |  15 +-
 .../apache/tajo/engine/planner/PlannerUtil.java |   2 +-
 .../tajo/engine/planner/TypeDeterminant.java    |  41 ++---
 .../planner/rewrite/ProjectionPushDownRule.java |   2 +-
 .../tajo/engine/eval/TestEvalTreeUtil.java      |   7 +-
 .../tajo/engine/planner/TestLogicalPlan.java    |  34 +---
 .../tajo/engine/query/TestGroupByQuery.java     |  54 +++++++
 .../apache/tajo/engine/query/TestJoinQuery.java |  28 ++++
 .../tajo/engine/query/TestSelectQuery.java      |  11 +-
 .../apache/tajo/engine/query/TestSortQuery.java |  17 ++
 .../tajo/engine/query/TestWindowQuery.java      |   7 +
 .../testGroupByWithConstantKeys3.sql            |   8 +
 .../testGroupByWithConstantKeys4.sql            |  12 ++
 .../testGroupByWithConstantKeys5.sql            |  13 ++
 .../testLeftOuterJoinWithConstantExpr4.sql      |   6 +
 .../testLeftOuterJoinWithConstantExpr5.sql      |   9 ++
 ...SelectSameConstantsWithDifferentAliases3.sql |  10 ++
 .../TestSortQuery/testSortWithConstKeys.sql     |  10 ++
 .../queries/TestWindowQuery/testWindow8.sql     |   7 +
 .../testGroupByWithConstantKeys3.result         |   3 +
 .../testGroupByWithConstantKeys4.result         |   5 +
 .../testGroupByWithConstantKeys5.result         |   5 +
 .../testLeftOuterJoinWithConstantExpr4.result   |   7 +
 .../testLeftOuterJoinWithConstantExpr5.result   |   6 +
 .../TestSelectQuery/testSelectAsterisk5.result  |   2 +-
 ...ectSameConstantsWithDifferentAliases3.result |   7 +
 .../TestSortQuery/testSortWithConstKeys.result  |   7 +
 .../testLocalQueryWithoutFrom.result            |   4 +-
 .../results/TestWindowQuery/testWindow8.result  |   7 +
 42 files changed, 856 insertions(+), 194 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tajo/blob/7e31a320/CHANGES
----------------------------------------------------------------------
diff --git a/CHANGES b/CHANGES
index f421aca..5d500a8 100644
--- a/CHANGES
+++ b/CHANGES
@@ -29,6 +29,9 @@ Release 0.9.0 - unreleased
 
   IMPROVEMENT
 
+    TAJO-895: ConstEval should not be included in target list of projectable 
+    nodes. (hyunsik)
+
     TAJO-928: Session variables should override query configs in TajoConf.
     (hyunsik)
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/7e31a320/tajo-core/src/main/java/org/apache/tajo/engine/eval/BinaryEval.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/eval/BinaryEval.java b/tajo-core/src/main/java/org/apache/tajo/engine/eval/BinaryEval.java
index 70d6bb1..2430020 100644
--- a/tajo-core/src/main/java/org/apache/tajo/engine/eval/BinaryEval.java
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/eval/BinaryEval.java
@@ -88,13 +88,23 @@ public class BinaryEval extends EvalNode implements Cloneable {
     return (T) this.rightExpr;
   }
 
-  public EvalNode getExpr(int id) {
+  public EvalNode getChild(int id) {
     if (id == 0) {
       return this.leftExpr;
     } else if (id == 1) {
       return this.rightExpr;
     } else {
-      throw new ArrayIndexOutOfBoundsException("only 0 or 1 is available (" + id + " is not available)");
+      throw new ArrayIndexOutOfBoundsException("only 0 or 1 is available, but (" + id + ") is not available)");
+    }
+  }
+
+  public void setChild(int id, EvalNode child) {
+    if (id == 0) {
+      this.leftExpr = child;
+    } else if (id == 1) {
+      this.rightExpr = child;
+    } else {
+      throw new ArrayIndexOutOfBoundsException("only 0 or 1 is available, but (" + id + ") is not available)");
     }
   }
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/7e31a320/tajo-core/src/main/java/org/apache/tajo/engine/eval/FunctionEval.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/eval/FunctionEval.java b/tajo-core/src/main/java/org/apache/tajo/engine/eval/FunctionEval.java
index 0cc8d98..376ee2e 100644
--- a/tajo-core/src/main/java/org/apache/tajo/engine/eval/FunctionEval.java
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/eval/FunctionEval.java
@@ -71,10 +71,14 @@ public abstract class FunctionEval extends EvalNode implements Cloneable {
 	  return this.argEvals;
 	}
 
+  public void setArg(int idx, EvalNode arg) {
+    this.argEvals[idx] = arg;
+  }
+
   public void setArgs(EvalNode [] args) {
     this.argEvals = args;
   }
-	
+
 	public DataType getValueType() {
 		return this.funcDesc.getReturnType();
 	}

http://git-wip-us.apache.org/repos/asf/tajo/blob/7e31a320/tajo-core/src/main/java/org/apache/tajo/engine/optimizer/eval/EvalTreeOptimizationRule.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/optimizer/eval/EvalTreeOptimizationRule.java b/tajo-core/src/main/java/org/apache/tajo/engine/optimizer/eval/EvalTreeOptimizationRule.java
new file mode 100644
index 0000000..2f17663
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/optimizer/eval/EvalTreeOptimizationRule.java
@@ -0,0 +1,27 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tajo.engine.optimizer.eval;
+
+import org.apache.tajo.engine.eval.EvalNode;
+import org.apache.tajo.engine.planner.LogicalPlanner;
+
+@Prioritized
+public interface EvalTreeOptimizationRule {
+  public EvalNode optimize(LogicalPlanner.PlanContext context, EvalNode tree);
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/7e31a320/tajo-core/src/main/java/org/apache/tajo/engine/optimizer/eval/EvalTreeOptimizer.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/optimizer/eval/EvalTreeOptimizer.java b/tajo-core/src/main/java/org/apache/tajo/engine/optimizer/eval/EvalTreeOptimizer.java
new file mode 100644
index 0000000..f5b4c06
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/optimizer/eval/EvalTreeOptimizer.java
@@ -0,0 +1,76 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tajo.engine.optimizer.eval;
+
+import com.google.common.collect.Lists;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.tajo.engine.eval.EvalNode;
+import org.apache.tajo.engine.planner.LogicalPlanner;
+import org.apache.tajo.util.ClassUtil;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Set;
+
+public class EvalTreeOptimizer {
+  private static final Log LOG = LogFactory.getLog(EvalTreeOptimizer.class);
+
+  private List<EvalTreeOptimizationRule> rules = Lists.newArrayList();
+
+  public EvalTreeOptimizer() {
+    Set<Class> functionClasses = ClassUtil.findClasses(EvalTreeOptimizationRule.class,
+        EvalTreeOptimizationRule.class.getPackage().getName() + ".rules");
+
+    for (Class eachRule : functionClasses) {
+      if (!EvalTreeOptimizationRule.class.isAssignableFrom(eachRule)) {
+        continue;
+      }
+
+      EvalTreeOptimizationRule rule = null;
+      try {
+        rule = (EvalTreeOptimizationRule)eachRule.newInstance();
+      } catch (Exception e) {
+        LOG.warn(eachRule + " cannot instantiate EvalTreeOptimizerRule class because of " + e.getMessage());
+        continue;
+      }
+      rules.add(rule);
+    }
+
+    Collections.sort(rules, new Comparator<EvalTreeOptimizationRule>() {
+      @Override
+      public int compare(EvalTreeOptimizationRule o1, EvalTreeOptimizationRule o2) {
+        int priority1 = o1.getClass().getAnnotation(Prioritized.class).priority();
+        int priority2 = o2.getClass().getAnnotation(Prioritized.class).priority();
+        return priority1 - priority2;
+      }
+    });
+  }
+
+  public EvalNode optimize(LogicalPlanner.PlanContext context, EvalNode node) {
+
+    EvalNode optimized = node;
+    for (EvalTreeOptimizationRule rule : rules) {
+      optimized = rule.optimize(context, optimized);
+    }
+
+    return optimized;
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/7e31a320/tajo-core/src/main/java/org/apache/tajo/engine/optimizer/eval/Prioritized.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/optimizer/eval/Prioritized.java b/tajo-core/src/main/java/org/apache/tajo/engine/optimizer/eval/Prioritized.java
new file mode 100644
index 0000000..865d895
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/optimizer/eval/Prioritized.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tajo.engine.optimizer.eval;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface Prioritized {
+  int priority() default 99;
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/7e31a320/tajo-core/src/main/java/org/apache/tajo/engine/optimizer/eval/rules/ConstantFolding.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/optimizer/eval/rules/ConstantFolding.java b/tajo-core/src/main/java/org/apache/tajo/engine/optimizer/eval/rules/ConstantFolding.java
new file mode 100644
index 0000000..b327e56
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/optimizer/eval/rules/ConstantFolding.java
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tajo.engine.optimizer.eval.rules;
+
+import org.apache.tajo.engine.eval.*;
+import org.apache.tajo.engine.optimizer.eval.EvalTreeOptimizationRule;
+import org.apache.tajo.engine.optimizer.eval.Prioritized;
+import org.apache.tajo.engine.planner.LogicalPlanner;
+
+import java.util.Stack;
+
+@Prioritized(priority = 10)
+public class ConstantFolding extends SimpleEvalNodeVisitor<LogicalPlanner.PlanContext>
+    implements EvalTreeOptimizationRule {
+
+  @Override
+  public EvalNode optimize(LogicalPlanner.PlanContext context, EvalNode evalNode) {
+    return visit(context, evalNode, new Stack<EvalNode>());
+  }
+
+  @Override
+  public EvalNode visitBinaryEval(LogicalPlanner.PlanContext context, Stack<EvalNode> stack, BinaryEval binaryEval) {
+    stack.push(binaryEval);
+    EvalNode lhs = visit(context, binaryEval.getLeftExpr(), stack);
+    EvalNode rhs = visit(context, binaryEval.getRightExpr(), stack);
+    stack.pop();
+
+    if (!binaryEval.getLeftExpr().equals(lhs)) {
+      binaryEval.setLeftExpr(lhs);
+    }
+    if (!binaryEval.getRightExpr().equals(rhs)) {
+      binaryEval.setRightExpr(rhs);
+    }
+
+    if (lhs.getType() == EvalType.CONST && rhs.getType() == EvalType.CONST) {
+      return new ConstEval(binaryEval.eval(null, null));
+    }
+
+    return binaryEval;
+  }
+
+  @Override
+  public EvalNode visitUnaryEval(LogicalPlanner.PlanContext context, Stack<EvalNode> stack, UnaryEval unaryEval) {
+    stack.push(unaryEval);
+    EvalNode child = visit(context, unaryEval.getChild(), stack);
+    stack.pop();
+
+    if (child.getType() == EvalType.CONST) {
+      return new ConstEval(unaryEval.eval(null, null));
+    }
+
+    return unaryEval;
+  }
+
+  @Override
+  public EvalNode visitFuncCall(LogicalPlanner.PlanContext context, FunctionEval evalNode, Stack<EvalNode> stack) {
+    boolean constantOfAllDescendents = true;
+
+    if ("sleep".equals(evalNode.getFuncDesc().getSignature())) {
+      constantOfAllDescendents = false;
+    } else {
+      if (evalNode.getArgs() != null) {
+        for (EvalNode arg : evalNode.getArgs()) {
+          arg = visit(context, arg, stack);
+          constantOfAllDescendents &= (arg.getType() == EvalType.CONST);
+        }
+      }
+    }
+
+    if (constantOfAllDescendents && evalNode.getType() == EvalType.FUNCTION) {
+      return new ConstEval(evalNode.eval(null, null));
+    } else {
+      return evalNode;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/7e31a320/tajo-core/src/main/java/org/apache/tajo/engine/optimizer/eval/rules/ConstantPropagation.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/optimizer/eval/rules/ConstantPropagation.java b/tajo-core/src/main/java/org/apache/tajo/engine/optimizer/eval/rules/ConstantPropagation.java
new file mode 100644
index 0000000..c7c6bd0
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/optimizer/eval/rules/ConstantPropagation.java
@@ -0,0 +1,112 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tajo.engine.optimizer.eval.rules;
+
+import org.apache.tajo.engine.eval.*;
+import org.apache.tajo.engine.optimizer.eval.EvalTreeOptimizationRule;
+import org.apache.tajo.engine.optimizer.eval.Prioritized;
+import org.apache.tajo.engine.planner.LogicalPlanner;
+
+import java.util.Stack;
+
+/**
+ * It replaces all field references which actually point to constant values by constant values.
+ * In order to maximize the effectiveness of constant folding, ConstantPropagation should be performed after
+ * constant folding.
+ */
+@Prioritized(priority = 15)
+public class ConstantPropagation extends SimpleEvalNodeVisitor<LogicalPlanner.PlanContext>
+    implements EvalTreeOptimizationRule {
+
+  @Override
+  public EvalNode optimize(LogicalPlanner.PlanContext context, EvalNode evalNode) {
+    if (evalNode.getType() == EvalType.FIELD) {
+      FieldEval fieldEval = (FieldEval) evalNode;
+
+      // if a reference points to a const value
+      if (context.getQueryBlock().isConstReference(fieldEval.getName())) {
+        return context.getQueryBlock().getConstByReference(fieldEval.getName());
+      } else {
+        return evalNode; // otherwise, it just returns.
+      }
+    } else {
+      return visit(context, evalNode, new Stack<EvalNode>());
+    }
+  }
+
+  @Override
+  public EvalNode visitBinaryEval(LogicalPlanner.PlanContext context, Stack<EvalNode> stack, BinaryEval binaryEval) {
+    stack.push(binaryEval);
+
+    for (int i = 0; i < 2; i++) {
+      if (binaryEval.getChild(i).getType() == EvalType.FIELD) {
+        FieldEval fieldEval = (FieldEval) binaryEval.getChild(i);
+        if (context.getQueryBlock().isConstReference(fieldEval.getName())) {
+          binaryEval.setChild(i, context.getQueryBlock().getConstByReference(fieldEval.getName()));
+          continue;
+        }
+      }
+
+      visit(context, binaryEval.getChild(i), stack);
+    }
+
+    stack.pop();
+
+    return binaryEval;
+  }
+
+  @Override
+  public EvalNode visitUnaryEval(LogicalPlanner.PlanContext context, Stack<EvalNode> stack, UnaryEval unaryEval) {
+    stack.push(unaryEval);
+
+    if (unaryEval.getChild().getType() == EvalType.FIELD) {
+      FieldEval fieldEval = (FieldEval) unaryEval.getChild();
+      if (context.getQueryBlock().isConstReference(fieldEval.getName())) {
+        unaryEval.setChild(context.getQueryBlock().getConstByReference(fieldEval.getName()));
+        stack.pop();
+        return unaryEval;
+      }
+    }
+    visit(context, unaryEval.getChild(), stack);
+    stack.pop();
+
+    return unaryEval;
+  }
+
+  @Override
+  public EvalNode visitFuncCall(LogicalPlanner.PlanContext context, FunctionEval function, Stack<EvalNode> stack) {
+    stack.push(function);
+
+    for (int i = 0; i < function.getArgs().length; i++) {
+      if (function.getArgs()[i].getType() == EvalType.FIELD) {
+        FieldEval fieldEval = (FieldEval) function.getArgs()[i];
+        if (context.getQueryBlock().isConstReference(fieldEval.getName())) {
+          function.setArg(i, context.getQueryBlock().getConstByReference(fieldEval.getName()));
+          continue;
+        }
+      }
+
+      visit(context, function.getArgs()[i], stack);
+    }
+
+    stack.pop();
+
+    return function;
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/7e31a320/tajo-core/src/main/java/org/apache/tajo/engine/planner/ExprAnnotator.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/planner/ExprAnnotator.java b/tajo-core/src/main/java/org/apache/tajo/engine/planner/ExprAnnotator.java
index 39fd08a..87e54de 100644
--- a/tajo-core/src/main/java/org/apache/tajo/engine/planner/ExprAnnotator.java
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/planner/ExprAnnotator.java
@@ -70,18 +70,18 @@ public class ExprAnnotator extends BaseAlgebraVisitor<ExprAnnotator.Context, Eva
     LogicalPlan.QueryBlock currentBlock;
     NameResolvingMode columnRsvLevel;
 
-    public Context(LogicalPlan plan, LogicalPlan.QueryBlock block, NameResolvingMode colRsvLevel) {
-      this.plan = plan;
-      this.currentBlock = block;
+    public Context(LogicalPlanner.PlanContext planContext, NameResolvingMode colRsvLevel) {
+      this.plan = planContext.plan;
+      this.currentBlock = planContext.queryBlock;
       this.columnRsvLevel = colRsvLevel;
     }
   }
 
-  public EvalNode createEvalNode(LogicalPlan plan, LogicalPlan.QueryBlock block, Expr expr,
+  public EvalNode createEvalNode(LogicalPlanner.PlanContext planContext, Expr expr,
                                  NameResolvingMode colRsvLevel)
       throws PlanningException {
-    Context context = new Context(plan, block, colRsvLevel);
-    return AlgebraicUtil.eliminateConstantExprs(visit(context, new Stack<Expr>(), expr));
+    Context context = new Context(planContext, colRsvLevel);
+    return planContext.evalOptimizer.optimize(planContext, visit(context, new Stack<Expr>(), expr));
   }
 
   public static void assertEval(boolean condition, String message) throws PlanningException {

http://git-wip-us.apache.org/repos/asf/tajo/blob/7e31a320/tajo-core/src/main/java/org/apache/tajo/engine/planner/ExprNormalizer.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/planner/ExprNormalizer.java b/tajo-core/src/main/java/org/apache/tajo/engine/planner/ExprNormalizer.java
index 5b61b74..3718056 100644
--- a/tajo-core/src/main/java/org/apache/tajo/engine/planner/ExprNormalizer.java
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/planner/ExprNormalizer.java
@@ -94,7 +94,7 @@ class ExprNormalizer extends SimpleAlgebraVisitor<ExprNormalizer.ExprNormalizedR
     List<NamedExpr> windowAggExprs = new ArrayList<NamedExpr>(); // window expressions which can be referred
     Set<WindowSpecReferences> windowSpecs = Sets.newLinkedHashSet();
 
-    private ExprNormalizedResult(LogicalPlanner.PlanContext context, boolean tryBinaryCommonTermsElimination) {
+    public ExprNormalizedResult(LogicalPlanner.PlanContext context, boolean tryBinaryCommonTermsElimination) {
       this.plan = context.plan;
       this.block = context.queryBlock;
       this.tryBinaryCommonTermsElimination = tryBinaryCommonTermsElimination;

http://git-wip-us.apache.org/repos/asf/tajo/blob/7e31a320/tajo-core/src/main/java/org/apache/tajo/engine/planner/LogicalPlan.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/planner/LogicalPlan.java b/tajo-core/src/main/java/org/apache/tajo/engine/planner/LogicalPlan.java
index ee65b2b..1cbe87a 100644
--- a/tajo-core/src/main/java/org/apache/tajo/engine/planner/LogicalPlan.java
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/planner/LogicalPlan.java
@@ -19,11 +19,13 @@
 package org.apache.tajo.engine.planner;
 
 import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
 import org.apache.commons.lang.ObjectUtils;
 import org.apache.tajo.algebra.*;
 import org.apache.tajo.annotation.NotThreadSafe;
 import org.apache.tajo.catalog.Column;
 import org.apache.tajo.catalog.Schema;
+import org.apache.tajo.engine.eval.ConstEval;
 import org.apache.tajo.engine.eval.EvalNode;
 import org.apache.tajo.engine.planner.graph.DirectedGraphCursor;
 import org.apache.tajo.engine.planner.graph.SimpleDirectedGraph;
@@ -190,6 +192,35 @@ public class LogicalPlan {
       FunctionExpr function = (FunctionExpr) expr;
       prefix = function.getSignature();
       break;
+    case Literal:
+      LiteralValue literal = (LiteralValue) expr;
+      switch (literal.getValueType()) {
+      case Boolean:
+        prefix = "bool";
+        break;
+      case String:
+        prefix = "text";
+        break;
+      case Unsigned_Integer:
+      case Unsigned_Large_Integer:
+        prefix = "number";
+        break;
+      case Unsigned_Float:
+        prefix = "real";
+        break;
+      default:
+        throw new IllegalStateException(literal.getValueType() + " is not implemented");
+      }
+      break;
+    case DateLiteral:
+      prefix = "date";
+      break;
+    case TimeLiteral:
+      prefix = "time";
+      break;
+    case TimestampLiteral:
+      prefix = "timestamp";
+      break;
     default:
       prefix = expr.getType().name();
     }
@@ -377,6 +408,8 @@ public class LogicalPlan {
     private final Map<OpType, List<Expr>> operatorToExprMap = TUtil.newHashMap();
     private final List<RelationNode> relationList = TUtil.newList();
     private boolean hasWindowFunction = false;
+    private final Map<String, ConstEval> constantPoolByRef = Maps.newHashMap();
+    private final Map<Expr, String> constantPool = Maps.newHashMap();
 
     /**
      * It's a map between nodetype and node. node types can be duplicated. So, latest node type is only kept.
@@ -401,7 +434,7 @@ public class LogicalPlan {
 
     public QueryBlock(String blockName) {
       this.blockName = blockName;
-      this.namedExprsMgr = new NamedExprsManager(LogicalPlan.this);
+      this.namedExprsMgr = new NamedExprsManager(LogicalPlan.this, this);
     }
 
     public String getName() {
@@ -472,6 +505,27 @@ public class LogicalPlan {
       return this.canonicalNameToRelationMap.size() > 0;
     }
 
+    public void addConstReference(String refName, Expr expr, ConstEval value) {
+      constantPoolByRef.put(refName, value);
+      constantPool.put(expr, refName);
+    }
+
+    public boolean isConstReference(String refName) {
+      return constantPoolByRef.containsKey(refName);
+    }
+
+    public boolean isRegisteredConst(Expr expr) {
+      return constantPool.containsKey(expr);
+    }
+
+    public String getConstReference(Expr expr) {
+      return constantPool.get(expr);
+    }
+
+    public ConstEval getConstByReference(String refName) {
+      return constantPoolByRef.get(refName);
+    }
+
     public void addColumnAlias(String original, String alias) {
       columnAliasMap.put(alias, original);
     }

http://git-wip-us.apache.org/repos/asf/tajo/blob/7e31a320/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 6ee0ff8..674525c 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
@@ -21,6 +21,7 @@ package org.apache.tajo.engine.planner;
 import org.apache.tajo.algebra.*;
 import org.apache.tajo.catalog.*;
 import org.apache.tajo.common.TajoDataTypes;
+import org.apache.tajo.engine.eval.ConstEval;
 import org.apache.tajo.engine.eval.EvalNode;
 import org.apache.tajo.engine.eval.FieldEval;
 import org.apache.tajo.engine.exception.NoSuchColumnException;
@@ -37,28 +38,10 @@ import java.util.*;
 /**
  * It finds all relations for each block and builds base schema information.
  */
-public class LogicalPlanPreprocessor extends BaseAlgebraVisitor<LogicalPlanPreprocessor.PreprocessContext, LogicalNode> {
+public class LogicalPlanPreprocessor extends BaseAlgebraVisitor<LogicalPlanner.PlanContext, LogicalNode> {
   private TypeDeterminant typeDeterminant;
   private ExprAnnotator annotator;
 
-  public static class PreprocessContext {
-    public QueryContext queryContext;
-    public LogicalPlan plan;
-    public LogicalPlan.QueryBlock currentBlock;
-
-    public PreprocessContext(QueryContext queryContext, LogicalPlan plan, LogicalPlan.QueryBlock currentBlock) {
-      this.queryContext = queryContext;
-      this.plan = plan;
-      this.currentBlock = currentBlock;
-    }
-
-    public PreprocessContext(PreprocessContext context, LogicalPlan.QueryBlock currentBlock) {
-      this.queryContext = context.queryContext;
-      this.plan = context.plan;
-      this.currentBlock = currentBlock;
-    }
-  }
-
   /** Catalog service */
   private CatalogService catalog;
 
@@ -69,19 +52,20 @@ public class LogicalPlanPreprocessor extends BaseAlgebraVisitor<LogicalPlanPrepr
   }
 
   @Override
-  public void preHook(PreprocessContext ctx, Stack<Expr> stack, Expr expr) throws PlanningException {
-    ctx.currentBlock.setAlgebraicExpr(expr);
-    ctx.plan.mapExprToBlock(expr, ctx.currentBlock.getName());
+  public void preHook(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, Expr expr) throws PlanningException {
+    ctx.queryBlock.setAlgebraicExpr(expr);
+    ctx.plan.mapExprToBlock(expr, ctx.queryBlock.getName());
   }
 
   @Override
-  public LogicalNode postHook(PreprocessContext ctx, Stack<Expr> stack, Expr expr, LogicalNode result) throws PlanningException {
+  public LogicalNode postHook(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, Expr expr, LogicalNode result)
+      throws PlanningException {
     // If non-from statement, result can be null. It avoids that case.
     if (result != null) {
       // setNode method registers each node to corresponding block and plan.
-      ctx.currentBlock.registerNode(result);
+      ctx.queryBlock.registerNode(result);
       // It makes a map between an expr and a logical node.
-      ctx.currentBlock.registerExprWithNode(expr, result);
+      ctx.queryBlock.registerExprWithNode(expr, result);
     }
     return result;
   }
@@ -93,10 +77,10 @@ public class LogicalPlanPreprocessor extends BaseAlgebraVisitor<LogicalPlanPrepr
    * @return array of columns
    * @throws PlanningException
    */
-  public static Column[] getColumns(PreprocessContext ctx, QualifiedAsteriskExpr asteriskExpr)
+  public static Column[] getColumns(LogicalPlanner.PlanContext ctx, QualifiedAsteriskExpr asteriskExpr)
       throws PlanningException {
     RelationNode relationOp = null;
-    QueryBlock block = ctx.currentBlock;
+    QueryBlock block = ctx.queryBlock;
     Collection<QueryBlock> queryBlocks = ctx.plan.getQueryBlocks();
     if (asteriskExpr.hasQualifier()) {
       String qualifier;
@@ -154,7 +138,7 @@ public class LogicalPlanPreprocessor extends BaseAlgebraVisitor<LogicalPlanPrepr
    * @return a list of NamedExpr each of which has ColumnReferenceExprs as its child
    * @throws PlanningException
    */
-  private static List<NamedExpr> resolveAsterisk(PreprocessContext ctx, QualifiedAsteriskExpr asteriskExpr)
+  private static List<NamedExpr> resolveAsterisk(LogicalPlanner.PlanContext ctx, QualifiedAsteriskExpr asteriskExpr)
       throws PlanningException {
     Column[] columns = getColumns(ctx, asteriskExpr);
     List<NamedExpr> newTargetExprs = new ArrayList<NamedExpr>(columns.length);
@@ -175,7 +159,8 @@ public class LogicalPlanPreprocessor extends BaseAlgebraVisitor<LogicalPlanPrepr
   }
 
   @Override
-  public LogicalNode visitProjection(PreprocessContext ctx, Stack<Expr> stack, Projection expr) throws PlanningException {
+  public LogicalNode visitProjection(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, Projection expr)
+      throws PlanningException {
     // If Non-from statement, it immediately returns.
     if (!expr.hasChild()) {
       return ctx.plan.createNode(EvalExprNode.class);
@@ -207,8 +192,12 @@ public class LogicalPlanPreprocessor extends BaseAlgebraVisitor<LogicalPlanPrepr
       normalizer.visit(ctx, new Stack<Expr>(), namedExpr.getExpr());
 
       if (namedExpr.getExpr().getType() == OpType.Column && namedExpr.hasAlias()) {
-        ctx.currentBlock.addColumnAlias(((ColumnReferenceExpr)namedExpr.getExpr()).getCanonicalName(),
+        ctx.queryBlock.addColumnAlias(((ColumnReferenceExpr)namedExpr.getExpr()).getCanonicalName(),
             namedExpr.getAlias());
+      } else if (OpType.isLiteralType(namedExpr.getExpr().getType()) && namedExpr.hasAlias()) {
+        Expr constExpr = namedExpr.getExpr();
+        ConstEval constEval = (ConstEval) annotator.createEvalNode(ctx, constExpr, NameResolvingMode.RELS_ONLY);
+        ctx.queryBlock.addConstReference(namedExpr.getAlias(), constExpr, constEval);
       }
     }
 
@@ -232,12 +221,13 @@ public class LogicalPlanPreprocessor extends BaseAlgebraVisitor<LogicalPlanPrepr
     projectionNode.setInSchema(child.getOutSchema());
     projectionNode.setOutSchema(PlannerUtil.targetToSchema(targets));
 
-    ctx.currentBlock.setSchema(projectionNode.getOutSchema());
+    ctx.queryBlock.setSchema(projectionNode.getOutSchema());
     return projectionNode;
   }
 
   @Override
-  public LogicalNode visitLimit(PreprocessContext ctx, Stack<Expr> stack, Limit expr) throws PlanningException {
+  public LogicalNode visitLimit(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, Limit expr)
+      throws PlanningException {
     stack.push(expr);
     LogicalNode child = visit(ctx, stack, expr.getChild());
     stack.pop();
@@ -249,7 +239,7 @@ public class LogicalPlanPreprocessor extends BaseAlgebraVisitor<LogicalPlanPrepr
   }
 
   @Override
-  public LogicalNode visitSort(PreprocessContext ctx, Stack<Expr> stack, Sort expr) throws PlanningException {
+  public LogicalNode visitSort(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, Sort expr) throws PlanningException {
     stack.push(expr);
     LogicalNode child = visit(ctx, stack, expr.getChild());
     stack.pop();
@@ -261,7 +251,8 @@ public class LogicalPlanPreprocessor extends BaseAlgebraVisitor<LogicalPlanPrepr
   }
 
   @Override
-  public LogicalNode visitHaving(PreprocessContext ctx, Stack<Expr> stack, Having expr) throws PlanningException {
+  public LogicalNode visitHaving(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, Having expr)
+      throws PlanningException {
     stack.push(expr);
     LogicalNode child = visit(ctx, stack, expr.getChild());
     stack.pop();
@@ -273,18 +264,18 @@ public class LogicalPlanPreprocessor extends BaseAlgebraVisitor<LogicalPlanPrepr
   }
 
   @Override
-  public LogicalNode visitGroupBy(PreprocessContext ctx, Stack<Expr> stack, Aggregation expr) throws PlanningException {
+  public LogicalNode visitGroupBy(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, Aggregation expr)
+      throws PlanningException {
     stack.push(expr); // <--- push
     LogicalNode child = visit(ctx, stack, expr.getChild());
 
-    Projection projection = ctx.currentBlock.getSingletonExpr(OpType.Projection);
+    Projection projection = ctx.queryBlock.getSingletonExpr(OpType.Projection);
     int finalTargetNum = projection.getNamedExprs().length;
     Target [] targets = new Target[finalTargetNum];
 
     for (int i = 0; i < finalTargetNum; i++) {
       NamedExpr namedExpr = projection.getNamedExprs()[i];
-      EvalNode evalNode = annotator.createEvalNode(ctx.plan, ctx.currentBlock, namedExpr.getExpr(),
-          NameResolvingMode.SUBEXPRS_AND_RELS);
+      EvalNode evalNode = annotator.createEvalNode(ctx, namedExpr.getExpr(), NameResolvingMode.SUBEXPRS_AND_RELS);
 
       if (namedExpr.hasAlias()) {
         targets[i] = new Target(evalNode, namedExpr.getAlias());
@@ -301,18 +292,19 @@ public class LogicalPlanPreprocessor extends BaseAlgebraVisitor<LogicalPlanPrepr
   }
 
   @Override
-  public LogicalNode visitUnion(PreprocessContext ctx, Stack<Expr> stack, SetOperation expr) throws PlanningException {
+  public LogicalNode visitUnion(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, SetOperation expr)
+      throws PlanningException {
     LogicalPlan.QueryBlock leftBlock = ctx.plan.newQueryBlock();
-    PreprocessContext leftContext = new PreprocessContext(ctx, leftBlock);
+    LogicalPlanner.PlanContext leftContext = new LogicalPlanner.PlanContext(ctx, leftBlock);
     LogicalNode leftChild = visit(leftContext, new Stack<Expr>(), expr.getLeft());
     leftBlock.setRoot(leftChild);
-    ctx.currentBlock.registerExprWithNode(expr.getLeft(), leftChild);
+    ctx.queryBlock.registerExprWithNode(expr.getLeft(), leftChild);
 
     LogicalPlan.QueryBlock rightBlock = ctx.plan.newQueryBlock();
-    PreprocessContext rightContext = new PreprocessContext(ctx, rightBlock);
+    LogicalPlanner.PlanContext rightContext = new LogicalPlanner.PlanContext(ctx, rightBlock);
     LogicalNode rightChild = visit(rightContext, new Stack<Expr>(), expr.getRight());
     rightBlock.setRoot(rightChild);
-    ctx.currentBlock.registerExprWithNode(expr.getRight(), rightChild);
+    ctx.queryBlock.registerExprWithNode(expr.getRight(), rightChild);
 
     UnionNode unionNode = new UnionNode(ctx.plan.newPID());
     unionNode.setLeftChild(leftChild);
@@ -323,7 +315,8 @@ public class LogicalPlanPreprocessor extends BaseAlgebraVisitor<LogicalPlanPrepr
     return unionNode;
   }
 
-  public LogicalNode visitFilter(PreprocessContext ctx, Stack<Expr> stack, Selection expr) throws PlanningException {
+  public LogicalNode visitFilter(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, Selection expr)
+      throws PlanningException {
     stack.push(expr);
     LogicalNode child = visit(ctx, stack, expr.getChild());
     stack.pop();
@@ -335,7 +328,7 @@ public class LogicalPlanPreprocessor extends BaseAlgebraVisitor<LogicalPlanPrepr
   }
 
   @Override
-  public LogicalNode visitJoin(PreprocessContext ctx, Stack<Expr> stack, Join expr) throws PlanningException {
+  public LogicalNode visitJoin(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, Join expr) throws PlanningException {
     stack.push(expr);
     LogicalNode left = visit(ctx, stack, expr.getLeft());
     LogicalNode right = visit(ctx, stack, expr.getRight());
@@ -346,12 +339,12 @@ public class LogicalPlanPreprocessor extends BaseAlgebraVisitor<LogicalPlanPrepr
     joinNode.setInSchema(merged);
     joinNode.setOutSchema(merged);
 
-    ctx.currentBlock.addJoinType(expr.getJoinType());
+    ctx.queryBlock.addJoinType(expr.getJoinType());
     return joinNode;
   }
 
   @Override
-  public LogicalNode visitRelation(PreprocessContext ctx, Stack<Expr> stack, Relation expr)
+  public LogicalNode visitRelation(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, Relation expr)
       throws PlanningException {
     Relation relation = expr;
 
@@ -369,27 +362,27 @@ public class LogicalPlanPreprocessor extends BaseAlgebraVisitor<LogicalPlanPrepr
     } else {
       scanNode.init(desc);
     }
-    ctx.currentBlock.addRelation(scanNode);
+    ctx.queryBlock.addRelation(scanNode);
 
     return scanNode;
   }
 
   @Override
-  public LogicalNode visitTableSubQuery(PreprocessContext ctx, Stack<Expr> stack, TablePrimarySubQuery expr)
+  public LogicalNode visitTableSubQuery(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, TablePrimarySubQuery expr)
       throws PlanningException {
 
-    PreprocessContext newContext;
+    LogicalPlanner.PlanContext newContext;
     // Note: TableSubQuery always has a table name.
     // SELECT .... FROM (SELECT ...) TB_NAME <-
     QueryBlock queryBlock = ctx.plan.newQueryBlock();
-    newContext = new PreprocessContext(ctx, queryBlock);
+    newContext = new LogicalPlanner.PlanContext(ctx, queryBlock);
     LogicalNode child = super.visitTableSubQuery(newContext, stack, expr);
     queryBlock.setRoot(child);
 
     // a table subquery should be dealt as a relation.
     TableSubQueryNode node = ctx.plan.createNode(TableSubQueryNode.class);
     node.init(CatalogUtil.buildFQName(ctx.queryContext.getCurrentDatabase(), expr.getName()), child);
-    ctx.currentBlock.addRelation(node);
+    ctx.queryBlock.addRelation(node);
     return node;
   }
 
@@ -398,21 +391,21 @@ public class LogicalPlanPreprocessor extends BaseAlgebraVisitor<LogicalPlanPrepr
   ///////////////////////////////////////////////////////////////////////////////////////////////////////////
 
   @Override
-  public LogicalNode visitCreateDatabase(PreprocessContext ctx, Stack<Expr> stack, CreateDatabase expr)
+  public LogicalNode visitCreateDatabase(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, CreateDatabase expr)
       throws PlanningException {
     CreateDatabaseNode createDatabaseNode = ctx.plan.createNode(CreateDatabaseNode.class);
     return createDatabaseNode;
   }
 
   @Override
-  public LogicalNode visitDropDatabase(PreprocessContext ctx, Stack<Expr> stack, DropDatabase expr)
+  public LogicalNode visitDropDatabase(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, DropDatabase expr)
       throws PlanningException {
     DropDatabaseNode dropDatabaseNode = ctx.plan.createNode(DropDatabaseNode.class);
     return dropDatabaseNode;
   }
 
   @Override
-  public LogicalNode visitCreateTable(PreprocessContext ctx, Stack<Expr> stack, CreateTable expr)
+  public LogicalNode visitCreateTable(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, CreateTable expr)
       throws PlanningException {
 
     CreateTableNode createTableNode = ctx.plan.createNode(CreateTableNode.class);
@@ -427,28 +420,28 @@ public class LogicalPlanPreprocessor extends BaseAlgebraVisitor<LogicalPlanPrepr
   }
 
   @Override
-  public LogicalNode visitDropTable(PreprocessContext ctx, Stack<Expr> stack, DropTable expr)
+  public LogicalNode visitDropTable(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, DropTable expr)
       throws PlanningException {
     DropTableNode dropTable = ctx.plan.createNode(DropTableNode.class);
     return dropTable;
   }
 
   @Override
-  public LogicalNode visitAlterTablespace(PreprocessContext ctx, Stack<Expr> stack, AlterTablespace expr)
+  public LogicalNode visitAlterTablespace(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, AlterTablespace expr)
       throws PlanningException {
     AlterTablespaceNode alterTablespace = ctx.plan.createNode(AlterTablespaceNode.class);
     return alterTablespace;
   }
 
   @Override
-  public LogicalNode visitAlterTable(PreprocessContext ctx, Stack<Expr> stack, AlterTable expr)
+  public LogicalNode visitAlterTable(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, AlterTable expr)
       throws PlanningException {
     AlterTableNode alterTableNode = ctx.plan.createNode(AlterTableNode.class);
     return alterTableNode;
   }
 
   @Override
-  public LogicalNode visitTruncateTable(PreprocessContext ctx, Stack<Expr> stack, TruncateTable expr)
+  public LogicalNode visitTruncateTable(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, TruncateTable expr)
       throws PlanningException {
     TruncateTableNode truncateTableNode = ctx.plan.createNode(TruncateTableNode.class);
     return truncateTableNode;
@@ -458,7 +451,8 @@ public class LogicalPlanPreprocessor extends BaseAlgebraVisitor<LogicalPlanPrepr
   // Insert or Update Section
   ///////////////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public LogicalNode visitInsert(PreprocessContext ctx, Stack<Expr> stack, Insert expr) throws PlanningException {
+  public LogicalNode visitInsert(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, Insert expr)
+      throws PlanningException {
     LogicalNode child = super.visitInsert(ctx, stack, expr);
 
     InsertNode insertNode = new InsertNode(ctx.plan.newPID());
@@ -467,12 +461,12 @@ public class LogicalPlanPreprocessor extends BaseAlgebraVisitor<LogicalPlanPrepr
     return insertNode;
   }
 
-  class NameRefInSelectListNormalizer extends SimpleAlgebraVisitor<PreprocessContext, Object> {
+  class NameRefInSelectListNormalizer extends SimpleAlgebraVisitor<LogicalPlanner.PlanContext, Object> {
     @Override
-    public Expr visitColumnReference(PreprocessContext ctx, Stack<Expr> stack, ColumnReferenceExpr expr)
+    public Expr visitColumnReference(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, ColumnReferenceExpr expr)
         throws PlanningException {
 
-      String normalized = NameResolver.resolve(ctx.plan, ctx.currentBlock, expr,
+      String normalized = NameResolver.resolve(ctx.plan, ctx.queryBlock, expr,
       NameResolvingMode.RELS_ONLY).getQualifiedName();
       expr.setName(normalized);
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/7e31a320/tajo-core/src/main/java/org/apache/tajo/engine/planner/LogicalPlanner.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/planner/LogicalPlanner.java b/tajo-core/src/main/java/org/apache/tajo/engine/planner/LogicalPlanner.java
index 35df11f..89382f4 100644
--- a/tajo-core/src/main/java/org/apache/tajo/engine/planner/LogicalPlanner.java
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/planner/LogicalPlanner.java
@@ -38,6 +38,7 @@ import org.apache.tajo.common.TajoDataTypes;
 import org.apache.tajo.datum.NullDatum;
 import org.apache.tajo.engine.eval.*;
 import org.apache.tajo.engine.exception.VerifyException;
+import org.apache.tajo.engine.optimizer.eval.EvalTreeOptimizer;
 import org.apache.tajo.engine.planner.LogicalPlan.QueryBlock;
 import org.apache.tajo.engine.planner.logical.*;
 import org.apache.tajo.engine.planner.nameresolver.NameResolvingMode;
@@ -54,7 +55,6 @@ import java.util.*;
 import static org.apache.tajo.algebra.CreateTable.PartitionType;
 import static org.apache.tajo.engine.planner.ExprNormalizer.ExprNormalizedResult;
 import static org.apache.tajo.engine.planner.LogicalPlan.BlockType;
-import static org.apache.tajo.engine.planner.LogicalPlanPreprocessor.PreprocessContext;
 
 /**
  * This class creates a logical plan from a nested tajo algebra expression ({@link org.apache.tajo.algebra})
@@ -63,6 +63,7 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
   private static Log LOG = LogFactory.getLog(LogicalPlanner.class);
   private final CatalogService catalog;
   private final LogicalPlanPreprocessor preprocessor;
+  private final EvalTreeOptimizer evalOptimizer;
   private final ExprAnnotator exprAnnotator;
   private final ExprNormalizer normalizer;
 
@@ -71,21 +72,22 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
     this.exprAnnotator = new ExprAnnotator(catalog);
     this.preprocessor = new LogicalPlanPreprocessor(catalog, exprAnnotator);
     this.normalizer = new ExprNormalizer();
+    this.evalOptimizer = new EvalTreeOptimizer();
   }
 
   public static class PlanContext {
     QueryContext queryContext;
     LogicalPlan plan;
-
-    // transient data for each query block
     QueryBlock queryBlock;
-
+    EvalTreeOptimizer evalOptimizer;
     boolean debugOrUnitTests;
 
-    public PlanContext(QueryContext context, LogicalPlan plan, QueryBlock block, boolean debugOrUnitTests) {
+    public PlanContext(QueryContext context, LogicalPlan plan, QueryBlock block, EvalTreeOptimizer evalOptimizer,
+                       boolean debugOrUnitTests) {
       this.queryContext = context;
       this.plan = plan;
       this.queryBlock = block;
+      this.evalOptimizer = evalOptimizer;
       this.debugOrUnitTests = debugOrUnitTests;
     }
 
@@ -93,9 +95,14 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
       this.queryContext = context.queryContext;
       this.plan = context.plan;
       this.queryBlock = block;
+      this.evalOptimizer = context.evalOptimizer;
       this.debugOrUnitTests = context.debugOrUnitTests;
     }
 
+    public QueryBlock getQueryBlock() {
+      return queryBlock;
+    }
+
     public String toString() {
       return "block=" + queryBlock.getName() + ", relNum=" + queryBlock.getRelations().size() + ", "+
           queryBlock.namedExprsMgr.toString();
@@ -118,11 +125,9 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
     LogicalPlan plan = new LogicalPlan(this);
 
     QueryBlock rootBlock = plan.newAndGetBlock(LogicalPlan.ROOT_BLOCK);
-    PreprocessContext preProcessorCtx = new PreprocessContext(queryContext, plan, rootBlock);
-    preprocessor.visit(preProcessorCtx, new Stack<Expr>(), expr);
+    PlanContext context = new PlanContext(queryContext, plan, rootBlock, evalOptimizer, debug);
+    preprocessor.visit(context, new Stack<Expr>(), expr);
     plan.resetGeneratedId();
-
-    PlanContext context = new PlanContext(queryContext, plan, plan.getRootBlock(), debug);
     LogicalNode topMostNode = this.visit(context, new Stack<Expr>(), expr);
 
     // Add Root Node
@@ -226,7 +231,7 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
 
     ProjectionNode projectionNode;
     Target [] targets;
-    targets = buildTargets(plan, block, referenceNames);
+    targets = buildTargets(context, referenceNames);
 
     // Set ProjectionNode
     projectionNode = context.queryBlock.getNodeFromExpr(projection);
@@ -261,8 +266,8 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
     Target [] rawTargets = new Target[projection.getNamedExprs().length];
     for (int i = 0; i < projection.getNamedExprs().length; i++) {
       NamedExpr namedExpr = projection.getNamedExprs()[i];
-      EvalNode evalNode = exprAnnotator.createEvalNode(plan, block, namedExpr.getExpr(),
-      NameResolvingMode.RELS_AND_SUBEXPRS);
+      EvalNode evalNode = exprAnnotator.createEvalNode(context, namedExpr.getExpr(),
+          NameResolvingMode.RELS_AND_SUBEXPRS);
       rawTargets[i] = new Target(evalNode, referenceNames[i]);
     }
     // it's for debugging or unit testing
@@ -341,8 +346,20 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
       }
 
       if (matcher.isMatch(namedExpr.getExpr())) {
-        // dissect an expression into multiple parts (at most dissected into three parts)
-        normalizedExprList[i] = normalizer.normalize(context, namedExpr.getExpr());
+        // If a value is constant value, it adds the constant value with a proper name to the constant map
+        // of the current block
+        if (!namedExpr.hasAlias() && OpType.isLiteralType(namedExpr.getExpr().getType())) {
+          String generatedName = context.plan.generateUniqueColumnName(namedExpr.getExpr());
+          ConstEval constEval = (ConstEval) exprAnnotator.createEvalNode(context, namedExpr.getExpr(),
+              NameResolvingMode.RELS_ONLY);
+          context.getQueryBlock().addConstReference(generatedName, namedExpr.getExpr(), constEval);
+          normalizedExprList[i] = new ExprNormalizedResult(context, false);
+          normalizedExprList[i].baseExpr = new ColumnReferenceExpr(generatedName);
+
+        } else {
+          // dissect an expression into multiple parts (at most dissected into three parts)
+          normalizedExprList[i] = normalizer.normalize(context, namedExpr.getExpr());
+        }
         targetIds.add(i);
       }
     }
@@ -385,7 +402,7 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
 
     for (int i = 0; i < targets.length; i++) {
       NamedExpr namedExpr = projection.getNamedExprs()[i];
-      EvalNode evalNode = exprAnnotator.createEvalNode(plan, block, namedExpr.getExpr(), NameResolvingMode.RELS_ONLY);
+      EvalNode evalNode = exprAnnotator.createEvalNode(context, namedExpr.getExpr(), NameResolvingMode.RELS_ONLY);
       if (namedExpr.hasAlias()) {
         targets[i] = new Target(evalNode, namedExpr.getAlias());
       } else {
@@ -400,19 +417,24 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
     return evalExprNode;
   }
 
-  private Target [] buildTargets(LogicalPlan plan, QueryBlock block, String[] referenceNames)
+  private Target [] buildTargets(PlanContext context, String[] referenceNames)
       throws PlanningException {
+    QueryBlock block = context.queryBlock;
+
     Target [] targets = new Target[referenceNames.length];
 
     for (int i = 0; i < referenceNames.length; i++) {
-      if (block.namedExprsMgr.isEvaluated(referenceNames[i])) {
-        targets[i] = block.namedExprsMgr.getTarget(referenceNames[i]);
+      String refName = referenceNames[i];
+      if (block.isConstReference(refName)) {
+        targets[i] = new Target(block.getConstByReference(refName), refName);
+      } else if (block.namedExprsMgr.isEvaluated(refName)) {
+        targets[i] = block.namedExprsMgr.getTarget(refName);
       } else {
-        NamedExpr namedExpr = block.namedExprsMgr.getNamedExpr(referenceNames[i]);
-        EvalNode evalNode = exprAnnotator.createEvalNode(plan, block, namedExpr.getExpr(),
+        NamedExpr namedExpr = block.namedExprsMgr.getNamedExpr(refName);
+        EvalNode evalNode = exprAnnotator.createEvalNode(context, namedExpr.getExpr(),
             NameResolvingMode.RELS_AND_SUBEXPRS);
-        block.namedExprsMgr.markAsEvaluated(referenceNames[i], evalNode);
-        targets[i] = new Target(evalNode, referenceNames[i]);
+        block.namedExprsMgr.markAsEvaluated(refName, evalNode);
+        targets[i] = new Target(evalNode, refName);
       }
     }
     return targets;
@@ -556,7 +578,7 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
     for (Iterator<NamedExpr> it = block.namedExprsMgr.getIteratorForUnevaluatedExprs(); it.hasNext();) {
       NamedExpr rawTarget = it.next();
       try {
-        EvalNode evalNode = exprAnnotator.createEvalNode(context.plan, context.queryBlock, rawTarget.getExpr(),
+        EvalNode evalNode = exprAnnotator.createEvalNode(context, rawTarget.getExpr(),
             NameResolvingMode.SUBEXPRS_AND_RELS);
         if (evalNode.getType() == EvalType.WINDOW_FUNCTION) {
           winFuncRefs.add(rawTarget.getAlias());
@@ -632,7 +654,11 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
     int targetIdx = 0;
     for (int i = 0; i < referenceNames.length ; i++) {
       if (!windowFuncIndices.contains(i)) {
-        targets[targetIdx++] = block.namedExprsMgr.getTarget(referenceNames[i]);
+        if (block.isConstReference(referenceNames[i])) {
+          targets[targetIdx++] = new Target(block.getConstByReference(referenceNames[i]), referenceNames[i]);
+        } else {
+          targets[targetIdx++] = block.namedExprsMgr.getTarget(referenceNames[i]);
+        }
       }
     }
     for (int i = 0; i < winFuncRefs.size(); i++) {
@@ -682,7 +708,7 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
       try {
         // check if at least distinct aggregation function
         includeDistinctFunction |= PlannerUtil.existsDistinctAggregationFunction(rawTarget.getExpr());
-        EvalNode evalNode = exprAnnotator.createEvalNode(context.plan, context.queryBlock, rawTarget.getExpr(),
+        EvalNode evalNode = exprAnnotator.createEvalNode(context, rawTarget.getExpr(),
             NameResolvingMode.SUBEXPRS_AND_RELS);
         if (evalNode.getType() == EvalType.AGG_FUNCTION) {
           aggEvalNames.add(rawTarget.getAlias());
@@ -717,7 +743,7 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
     EvalNode firstFetNum;
     LogicalNode child;
     if (limit.getFetchFirstNum().getType() == OpType.Literal) {
-      firstFetNum = exprAnnotator.createEvalNode(context.plan, block, limit.getFetchFirstNum(),
+      firstFetNum = exprAnnotator.createEvalNode(context, limit.getFetchFirstNum(),
           NameResolvingMode.RELS_ONLY);
 
       ////////////////////////////////////////////////////////
@@ -745,8 +771,7 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
         firstFetNum = block.namedExprsMgr.getTarget(referName).getEvalTree();
       } else {
         NamedExpr namedExpr = block.namedExprsMgr.getNamedExpr(referName);
-        firstFetNum = exprAnnotator.createEvalNode(context.plan, block, namedExpr.getExpr(),
-            NameResolvingMode.SUBEXPRS_AND_RELS);
+        firstFetNum = exprAnnotator.createEvalNode(context, namedExpr.getExpr(), NameResolvingMode.SUBEXPRS_AND_RELS);
         block.namedExprsMgr.markAsEvaluated(referName, firstFetNum);
       }
     }
@@ -761,7 +786,7 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
   }
 
   @Override
-  public SortNode visitSort(PlanContext context, Stack<Expr> stack, Sort sort) throws PlanningException {
+  public LogicalNode visitSort(PlanContext context, Stack<Expr> stack, Sort sort) throws PlanningException {
     QueryBlock block = context.queryBlock;
 
     int sortKeyNum = sort.getSortSpecs().length;
@@ -797,18 +822,25 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
 
     // Building sort keys
     Column column;
-    SortSpec [] annotatedSortSpecs = new SortSpec[sortKeyNum];
+    List<SortSpec> annotatedSortSpecs = Lists.newArrayList();
     for (int i = 0; i < sortKeyNum; i++) {
-      if (block.namedExprsMgr.isEvaluated(referNames[i])) {
-        column = block.namedExprsMgr.getTarget(referNames[i]).getNamedColumn();
+      String refName = referNames[i];
+      if (block.isConstReference(refName)) {
+        continue;
+      } else if (block.namedExprsMgr.isEvaluated(refName)) {
+        column = block.namedExprsMgr.getTarget(refName).getNamedColumn();
       } else {
         throw new IllegalStateException("Unexpected State: " + TUtil.arrayToString(sortSpecs));
       }
-      annotatedSortSpecs[i] = new SortSpec(column, sortSpecs[i].isAscending(), sortSpecs[i].isNullFirst());
+      annotatedSortSpecs.add(new SortSpec(column, sortSpecs[i].isAscending(), sortSpecs[i].isNullFirst()));
     }
 
-    sortNode.setSortSpecs(annotatedSortSpecs);
-    return sortNode;
+    if (annotatedSortSpecs.size() == 0) {
+      return child;
+    } else {
+      sortNode.setSortSpecs(annotatedSortSpecs.toArray(new SortSpec[annotatedSortSpecs.size()]));
+      return sortNode;
+    }
   }
 
   /*===============================================================================================
@@ -842,7 +874,7 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
       havingCondition = block.namedExprsMgr.getTarget(referName).getEvalTree();
     } else {
       NamedExpr namedExpr = block.namedExprsMgr.getNamedExpr(referName);
-      havingCondition = exprAnnotator.createEvalNode(context.plan, block, namedExpr.getExpr(),
+      havingCondition = exprAnnotator.createEvalNode(context, namedExpr.getExpr(),
           NameResolvingMode.SUBEXPRS_AND_RELS);
       block.namedExprsMgr.markAsEvaluated(referName, havingCondition);
     }
@@ -888,15 +920,20 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
     groupingNode.setInSchema(child.getOutSchema());
 
     // Set grouping sets
-    Column [] groupingColumns = new Column[aggregation.getGroupSet()[0].getGroupingSets().length];
-    for (int i = 0; i < groupingColumns.length; i++) {
-      if (block.namedExprsMgr.isEvaluated(groupingKeyRefNames[i])) {
-        groupingColumns[i] = block.namedExprsMgr.getTarget(groupingKeyRefNames[i]).getNamedColumn();
+    List<Column> groupingColumns = Lists.newArrayList();
+    for (int i = 0; i < groupingKeyRefNames.length; i++) {
+      String refName = groupingKeyRefNames[i];
+      if (context.getQueryBlock().isConstReference(refName)) {
+        continue;
+      } else if (block.namedExprsMgr.isEvaluated(groupingKeyRefNames[i])) {
+        groupingColumns.add(block.namedExprsMgr.getTarget(groupingKeyRefNames[i]).getNamedColumn());
       } else {
         throw new PlanningException("Each grouping column expression must be a scalar expression.");
       }
     }
-    groupingNode.setGroupingColumns(groupingColumns);
+
+    int effectiveGroupingKeyNum = groupingColumns.size();
+    groupingNode.setGroupingColumns(groupingColumns.toArray(new Column[effectiveGroupingKeyNum]));
 
     ////////////////////////////////////////////////////////
     // Visit and Build Child Plan
@@ -910,7 +947,7 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
       NamedExpr namedExpr = iterator.next();
       try {
         includeDistinctFunction |= PlannerUtil.existsDistinctAggregationFunction(namedExpr.getExpr());
-        EvalNode evalNode = exprAnnotator.createEvalNode(context.plan, context.queryBlock, namedExpr.getExpr(),
+        EvalNode evalNode = exprAnnotator.createEvalNode(context, namedExpr.getExpr(),
             NameResolvingMode.SUBEXPRS_AND_RELS);
         if (evalNode.getType() == EvalType.AGG_FUNCTION) {
           block.namedExprsMgr.markAsEvaluated(namedExpr.getAlias(), evalNode);
@@ -924,7 +961,7 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
     groupingNode.setDistinct(includeDistinctFunction);
     groupingNode.setAggFunctions(aggEvalNodes.toArray(new AggregationFunctionCallEval[aggEvalNodes.size()]));
 
-    Target [] targets = new Target[groupingKeyNum + aggEvalNames.size()];
+    Target [] targets = new Target[effectiveGroupingKeyNum + aggEvalNames.size()];
 
     // In target, grouping columns will be followed by aggregation evals.
     //
@@ -933,12 +970,12 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
     //  grouping keys      aggregation evals
 
     // Build grouping keys
-    for (int i = 0; i < groupingKeyNum; i++) {
+    for (int i = 0; i < effectiveGroupingKeyNum; i++) {
       Target target = block.namedExprsMgr.getTarget(groupingNode.getGroupingColumns()[i].getQualifiedName());
       targets[i] = target;
     }
 
-    for (int i = 0, targetIdx = groupingKeyNum; i < aggEvalNodes.size(); i++, targetIdx++) {
+    for (int i = 0, targetIdx = effectiveGroupingKeyNum; i < aggEvalNodes.size(); i++, targetIdx++) {
       targets[targetIdx] = block.namedExprsMgr.getTarget(aggEvalNames.get(i));
     }
 
@@ -997,9 +1034,9 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
     selectionNode.setOutSchema(child.getOutSchema());
 
     // Create EvalNode for a search condition.
-    EvalNode searchCondition = exprAnnotator.createEvalNode(context.plan, block, selection.getQual(),
+    EvalNode searchCondition = exprAnnotator.createEvalNode(context, selection.getQual(),
         NameResolvingMode.RELS_AND_SUBEXPRS);
-    EvalNode simplified = AlgebraicUtil.eliminateConstantExprs(searchCondition);
+    EvalNode simplified = context.evalOptimizer.optimize(context, searchCondition);
     // set selection condition
     selectionNode.setQual(simplified);
 
@@ -1051,12 +1088,11 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
     // Create EvalNode for a search condition.
     EvalNode joinCondition = null;
     if (join.hasQual()) {
-      EvalNode evalNode = exprAnnotator.createEvalNode(context.plan, block, join.getQual(),
-          NameResolvingMode.LEGACY);
-      joinCondition = AlgebraicUtil.eliminateConstantExprs(evalNode);
+      EvalNode evalNode = exprAnnotator.createEvalNode(context, join.getQual(), NameResolvingMode.LEGACY);
+      joinCondition = context.evalOptimizer.optimize(context, evalNode);
     }
 
-    List<String> newlyEvaluatedExprs = getNewlyEvaluatedExprsForJoin(plan, block, joinNode, stack);
+    List<String> newlyEvaluatedExprs = getNewlyEvaluatedExprsForJoin(context, joinNode, stack);
     List<Target> targets = TUtil.newList(PlannerUtil.schemaToTargets(merged));
 
     for (String newAddedExpr : newlyEvaluatedExprs) {
@@ -1075,14 +1111,15 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
     return joinNode;
   }
 
-  private List<String> getNewlyEvaluatedExprsForJoin(LogicalPlan plan, QueryBlock block, JoinNode joinNode,
-                                                   Stack<Expr> stack) {
+  private List<String> getNewlyEvaluatedExprsForJoin(PlanContext context, JoinNode joinNode, Stack<Expr> stack) {
+    QueryBlock block = context.queryBlock;
+
     EvalNode evalNode;
     List<String> newlyEvaluatedExprs = TUtil.newList();
     for (Iterator<NamedExpr> it = block.namedExprsMgr.getIteratorForUnevaluatedExprs(); it.hasNext();) {
       NamedExpr namedExpr = it.next();
       try {
-        evalNode = exprAnnotator.createEvalNode(plan, block, namedExpr.getExpr(), NameResolvingMode.LEGACY);
+        evalNode = exprAnnotator.createEvalNode(context, namedExpr.getExpr(), NameResolvingMode.LEGACY);
         if (LogicalPlanner.checkIfBeEvaluatedAtJoin(block, evalNode, joinNode, stack.peek().getType() != OpType.Join)) {
           block.namedExprsMgr.markAsEvaluated(namedExpr.getAlias(), evalNode);
           newlyEvaluatedExprs.add(namedExpr.getAlias());
@@ -1152,7 +1189,7 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
     for (Iterator<NamedExpr> it = block.namedExprsMgr.getIteratorForUnevaluatedExprs(); it.hasNext();) {
       NamedExpr namedExpr = it.next();
       try {
-        evalNode = exprAnnotator.createEvalNode(plan, block, namedExpr.getExpr(), NameResolvingMode.LEGACY);
+        evalNode = exprAnnotator.createEvalNode(context, namedExpr.getExpr(), NameResolvingMode.LEGACY);
         if (EvalTreeUtil.findDistinctAggFunction(evalNode).size() == 0) {
           block.namedExprsMgr.markAsEvaluated(namedExpr.getAlias(), evalNode);
           newlyEvaluatedExprs.add(namedExpr.getAlias());
@@ -1204,7 +1241,7 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
     for (Iterator<NamedExpr> iterator = block.namedExprsMgr.getIteratorForUnevaluatedExprs(); iterator.hasNext();) {
       NamedExpr rawTarget = iterator.next();
       try {
-        EvalNode evalNode = exprAnnotator.createEvalNode(context.plan, context.queryBlock, rawTarget.getExpr(),
+        EvalNode evalNode = exprAnnotator.createEvalNode(context, rawTarget.getExpr(),
             NameResolvingMode.RELS_ONLY);
         if (checkIfBeEvaluatedAtRelation(block, evalNode, scanNode)) {
           block.namedExprsMgr.markAsEvaluated(rawTarget.getAlias(), evalNode);
@@ -1221,8 +1258,7 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
     // So, we get a raw expression and then creates a target.
     for (String reference : newlyEvaluatedExprsReferences) {
       NamedExpr refrer = block.namedExprsMgr.getNamedExpr(reference);
-      EvalNode evalNode = exprAnnotator.createEvalNode(context.plan, block, refrer.getExpr(),
-          NameResolvingMode.RELS_ONLY);
+      EvalNode evalNode = exprAnnotator.createEvalNode(context, refrer.getExpr(), NameResolvingMode.RELS_ONLY);
       targets.add(new Target(evalNode, reference));
     }
 
@@ -1280,7 +1316,7 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
     Set<String> newlyEvaluatedExprs = TUtil.newHashSet();
     for (NamedExpr rawTarget : block.namedExprsMgr.getAllNamedExprs()) {
       try {
-        EvalNode evalNode = exprAnnotator.createEvalNode(context.plan, context.queryBlock, rawTarget.getExpr(),
+        EvalNode evalNode = exprAnnotator.createEvalNode(context, rawTarget.getExpr(),
             NameResolvingMode.RELS_ONLY);
         if (checkIfBeEvaluatedAtRelation(block, evalNode, subQueryNode)) {
           block.namedExprsMgr.markAsEvaluated(rawTarget.getAlias(), evalNode);

http://git-wip-us.apache.org/repos/asf/tajo/blob/7e31a320/tajo-core/src/main/java/org/apache/tajo/engine/planner/NamedExprsManager.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/planner/NamedExprsManager.java b/tajo-core/src/main/java/org/apache/tajo/engine/planner/NamedExprsManager.java
index 710dad8..8666a5c 100644
--- a/tajo-core/src/main/java/org/apache/tajo/engine/planner/NamedExprsManager.java
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/planner/NamedExprsManager.java
@@ -78,10 +78,13 @@ public class NamedExprsManager {
   /** Map: Alias Name <-> Original Name */
   private BiMap<String, String> aliasedColumnMap = HashBiMap.create();
 
-  private LogicalPlan plan;
+  private final LogicalPlan plan;
 
-  public NamedExprsManager(LogicalPlan plan) {
+  private final LogicalPlan.QueryBlock block;
+
+  public NamedExprsManager(LogicalPlan plan, LogicalPlan.QueryBlock block) {
     this.plan = plan;
+    this.block = block;
   }
 
   private int getNextId() {
@@ -145,6 +148,10 @@ public class NamedExprsManager {
       return idToNamesMap.get(refId).get(0);
     }
 
+    if (block.isRegisteredConst(expr)) {
+      return block.getConstReference(expr);
+    }
+
     String generatedName = plan.generateUniqueColumnName(expr);
     return addExpr(expr, generatedName);
   }
@@ -155,6 +162,10 @@ public class NamedExprsManager {
    */
   public String addExpr(Expr expr, String alias) throws PlanningException {
 
+    if (OpType.isLiteralType(expr.getType())) {
+      return alias;
+    }
+
     // if this name already exists, just returns the name.
     if (nameToIdMap.containsKey(alias)) {
       return alias;

http://git-wip-us.apache.org/repos/asf/tajo/blob/7e31a320/tajo-core/src/main/java/org/apache/tajo/engine/planner/PlannerUtil.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/planner/PlannerUtil.java b/tajo-core/src/main/java/org/apache/tajo/engine/planner/PlannerUtil.java
index 55892ee..3390758 100644
--- a/tajo-core/src/main/java/org/apache/tajo/engine/planner/PlannerUtil.java
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/planner/PlannerUtil.java
@@ -589,7 +589,7 @@ public class PlannerUtil {
         Column[] pair = new Column[2];
 
         for (int i = 0; i <= 1; i++) { // access left, right sub expression
-          Column column = EvalTreeUtil.findAllColumnRefs(binaryEval.getExpr(i)).get(0);
+          Column column = EvalTreeUtil.findAllColumnRefs(binaryEval.getChild(i)).get(0);
           for (int j = 0; j < schemas.length; j++) {
             // check whether the column is for either outer or inner
             // 0 is outer, and 1 is inner

http://git-wip-us.apache.org/repos/asf/tajo/blob/7e31a320/tajo-core/src/main/java/org/apache/tajo/engine/planner/TypeDeterminant.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/planner/TypeDeterminant.java b/tajo-core/src/main/java/org/apache/tajo/engine/planner/TypeDeterminant.java
index 2e3c1c1..275e056 100644
--- a/tajo-core/src/main/java/org/apache/tajo/engine/planner/TypeDeterminant.java
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/planner/TypeDeterminant.java
@@ -33,9 +33,8 @@ import java.util.Stack;
 import static org.apache.tajo.common.TajoDataTypes.DataType;
 import static org.apache.tajo.common.TajoDataTypes.Type.BOOLEAN;
 import static org.apache.tajo.common.TajoDataTypes.Type.NULL_TYPE;
-import static org.apache.tajo.engine.planner.LogicalPlanPreprocessor.PreprocessContext;
 
-public class TypeDeterminant extends SimpleAlgebraVisitor<PreprocessContext, DataType> {
+public class TypeDeterminant extends SimpleAlgebraVisitor<LogicalPlanner.PlanContext, DataType> {
   private DataType BOOL_TYPE = CatalogUtil.newSimpleDataType(BOOLEAN);
   private CatalogService catalog;
 
@@ -43,12 +42,13 @@ public class TypeDeterminant extends SimpleAlgebraVisitor<PreprocessContext, Dat
     this.catalog = catalog;
   }
 
-  public DataType determineDataType(PreprocessContext ctx, Expr expr) throws PlanningException {
+  public DataType determineDataType(LogicalPlanner.PlanContext ctx, Expr expr) throws PlanningException {
     return visit(ctx, new Stack<Expr>(), expr);
   }
 
   @Override
-  public DataType visitUnaryOperator(PreprocessContext ctx, Stack<Expr> stack, UnaryOperator expr) throws PlanningException {
+  public DataType visitUnaryOperator(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, UnaryOperator expr)
+      throws PlanningException {
     stack.push(expr);
     DataType dataType = null;
     switch (expr.getType()) {
@@ -67,7 +67,7 @@ public class TypeDeterminant extends SimpleAlgebraVisitor<PreprocessContext, Dat
   }
 
   @Override
-  public DataType visitBinaryOperator(PreprocessContext ctx, Stack<Expr> stack, BinaryOperator expr)
+  public DataType visitBinaryOperator(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, BinaryOperator expr)
       throws PlanningException {
     stack.push(expr);
     DataType lhsType = visit(ctx, stack, expr.getLeft());
@@ -97,13 +97,13 @@ public class TypeDeterminant extends SimpleAlgebraVisitor<PreprocessContext, Dat
   ///////////////////////////////////////////////////////////////////////////////////////////////////////////
 
   @Override
-  public DataType visitBetween(PreprocessContext ctx, Stack<Expr> stack, BetweenPredicate expr)
+  public DataType visitBetween(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, BetweenPredicate expr)
       throws PlanningException {
     return CatalogUtil.newSimpleDataType(BOOLEAN);
   }
 
   @Override
-  public DataType visitCaseWhen(PreprocessContext ctx, Stack<Expr> stack, CaseWhenPredicate caseWhen)
+  public DataType visitCaseWhen(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, CaseWhenPredicate caseWhen)
       throws PlanningException {
     DataType lastDataType = null;
 
@@ -129,10 +129,10 @@ public class TypeDeterminant extends SimpleAlgebraVisitor<PreprocessContext, Dat
   ///////////////////////////////////////////////////////////////////////////////////////////////////////////
 
   @Override
-  public DataType visitColumnReference(PreprocessContext ctx, Stack<Expr> stack, ColumnReferenceExpr expr)
+  public DataType visitColumnReference(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, ColumnReferenceExpr expr)
       throws PlanningException {
     stack.push(expr);
-    Column column = ctx.plan.resolveColumn(ctx.currentBlock, expr);
+    Column column = ctx.plan.resolveColumn(ctx.queryBlock, expr);
     stack.pop();
     return column.getDataType();
   }
@@ -142,7 +142,8 @@ public class TypeDeterminant extends SimpleAlgebraVisitor<PreprocessContext, Dat
   ///////////////////////////////////////////////////////////////////////////////////////////////////////////
 
   @Override
-  public DataType visitFunction(PreprocessContext ctx, Stack<Expr> stack, FunctionExpr expr) throws PlanningException {
+  public DataType visitFunction(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, FunctionExpr expr)
+      throws PlanningException {
     stack.push(expr); // <--- Push
 
     // Given parameters
@@ -170,7 +171,7 @@ public class TypeDeterminant extends SimpleAlgebraVisitor<PreprocessContext, Dat
   }
 
   @Override
-  public DataType visitCountRowsFunction(PreprocessContext ctx, Stack<Expr> stack, CountRowsFunctionExpr expr)
+  public DataType visitCountRowsFunction(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, CountRowsFunctionExpr expr)
       throws PlanningException {
     FunctionDesc countRows = catalog.getFunction("count", CatalogProtos.FunctionType.AGGREGATION,
         new DataType[] {});
@@ -178,8 +179,8 @@ public class TypeDeterminant extends SimpleAlgebraVisitor<PreprocessContext, Dat
   }
 
   @Override
-  public DataType visitGeneralSetFunction(PreprocessContext ctx, Stack<Expr> stack, GeneralSetFunctionExpr setFunction)
-      throws PlanningException {
+  public DataType visitGeneralSetFunction(LogicalPlanner.PlanContext ctx, Stack<Expr> stack,
+                                          GeneralSetFunctionExpr setFunction) throws PlanningException {
     stack.push(setFunction);
 
     Expr[] params = setFunction.getParams();
@@ -206,7 +207,7 @@ public class TypeDeterminant extends SimpleAlgebraVisitor<PreprocessContext, Dat
   }
 
   @Override
-  public DataType visitWindowFunction(PreprocessContext ctx, Stack<Expr> stack, WindowFunctionExpr windowFunc)
+  public DataType visitWindowFunction(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, WindowFunctionExpr windowFunc)
       throws PlanningException {
     stack.push(windowFunc); // <--- Push
 
@@ -257,12 +258,14 @@ public class TypeDeterminant extends SimpleAlgebraVisitor<PreprocessContext, Dat
   ///////////////////////////////////////////////////////////////////////////////////////////////////////////
 
   @Override
-  public DataType visitDataType(PreprocessContext ctx, Stack<Expr> stack, DataTypeExpr expr) throws PlanningException {
+  public DataType visitDataType(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, DataTypeExpr expr)
+      throws PlanningException {
     return LogicalPlanner.convertDataType(expr);
   }
 
   @Override
-  public DataType visitLiteral(PreprocessContext ctx, Stack<Expr> stack, LiteralValue expr) throws PlanningException {
+  public DataType visitLiteral(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, LiteralValue expr)
+      throws PlanningException {
     // It must be the same to ExprAnnotator::visitLiteral.
 
     switch (expr.getValueType()) {
@@ -282,19 +285,19 @@ public class TypeDeterminant extends SimpleAlgebraVisitor<PreprocessContext, Dat
   }
 
   @Override
-  public DataType visitNullLiteral(PreprocessContext ctx, Stack<Expr> stack, NullLiteral expr)
+  public DataType visitNullLiteral(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, NullLiteral expr)
       throws PlanningException {
     return CatalogUtil.newSimpleDataType(NULL_TYPE);
   }
 
   @Override
-  public DataType visitTimestampLiteral(PreprocessContext ctx, Stack<Expr> stack, TimestampLiteral expr)
+  public DataType visitTimestampLiteral(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, TimestampLiteral expr)
       throws PlanningException {
     return CatalogUtil.newSimpleDataType(TajoDataTypes.Type.TIMESTAMP);
   }
 
   @Override
-  public DataType visitTimeLiteral(PreprocessContext ctx, Stack<Expr> stack, TimeLiteral expr)
+  public DataType visitTimeLiteral(LogicalPlanner.PlanContext ctx, Stack<Expr> stack, TimeLiteral expr)
       throws PlanningException {
     return CatalogUtil.newSimpleDataType(TajoDataTypes.Type.TIME);
   }

http://git-wip-us.apache.org/repos/asf/tajo/blob/7e31a320/tajo-core/src/main/java/org/apache/tajo/engine/planner/rewrite/ProjectionPushDownRule.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/planner/rewrite/ProjectionPushDownRule.java b/tajo-core/src/main/java/org/apache/tajo/engine/planner/rewrite/ProjectionPushDownRule.java
index 4a12d99..ec5df04 100644
--- a/tajo-core/src/main/java/org/apache/tajo/engine/planner/rewrite/ProjectionPushDownRule.java
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/planner/rewrite/ProjectionPushDownRule.java
@@ -863,7 +863,7 @@ public class ProjectionPushDownRule extends
           BinaryEval binaryQual = (BinaryEval) eachQual;
 
           for (int i = 0; i < 2; i++) {
-            EvalNode term = binaryQual.getExpr(i);
+            EvalNode term = binaryQual.getChild(i);
             pushDownIfComplexTermInJoinCondition(newContext, eachQual, term);
           }
         }

http://git-wip-us.apache.org/repos/asf/tajo/blob/7e31a320/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 35f5aa2..2a37c9b 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
@@ -32,6 +32,7 @@ import org.apache.tajo.common.TajoDataTypes;
 import org.apache.tajo.datum.Datum;
 import org.apache.tajo.datum.DatumFactory;
 import org.apache.tajo.engine.function.GeneralFunction;
+import org.apache.tajo.engine.optimizer.eval.EvalTreeOptimizer;
 import org.apache.tajo.engine.parser.SQLAnalyzer;
 import org.apache.tajo.engine.planner.LogicalPlan;
 import org.apache.tajo.engine.planner.LogicalPlanner;
@@ -148,6 +149,7 @@ public class TestEvalTreeUtil {
   }
 
   public static EvalNode getRootSelection(String query) throws PlanningException {
+
     Expr block = analyzer.parse(query);
     LogicalPlan plan = null;
     try {
@@ -156,8 +158,11 @@ public class TestEvalTreeUtil {
       e.printStackTrace();
     }
 
+    LogicalPlanner.PlanContext context = new LogicalPlanner.PlanContext(defaultContext, plan, plan.getRootBlock(),
+        new EvalTreeOptimizer(), true);
+
     Selection selection = plan.getRootBlock().getSingletonExpr(OpType.Filter);
-    return planner.getExprAnnotator().createEvalNode(plan, plan.getRootBlock(), selection.getQual(),
+    return planner.getExprAnnotator().createEvalNode(context, selection.getQual(),
         NameResolvingMode.RELS_AND_SUBEXPRS);
   }
 

http://git-wip-us.apache.org/repos/asf/tajo/blob/7e31a320/tajo-core/src/test/java/org/apache/tajo/engine/planner/TestLogicalPlan.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/test/java/org/apache/tajo/engine/planner/TestLogicalPlan.java b/tajo-core/src/test/java/org/apache/tajo/engine/planner/TestLogicalPlan.java
index 934beef..1f8fc35 100644
--- a/tajo-core/src/test/java/org/apache/tajo/engine/planner/TestLogicalPlan.java
+++ b/tajo-core/src/test/java/org/apache/tajo/engine/planner/TestLogicalPlan.java
@@ -40,45 +40,13 @@ import static org.junit.Assert.*;
 
 public class TestLogicalPlan {
   private static TajoTestingCluster util;
-  private static TPCH tpch;
-  private static CatalogService catalog;
-  private static SQLAnalyzer sqlAnalyzer = new SQLAnalyzer();
   private static LogicalPlanner planner;
-  private static LogicalOptimizer optimizer;
 
   @BeforeClass
   public static void setup() throws Exception {
     util = new TajoTestingCluster();
     util.startCatalogCluster();
-    catalog = util.getMiniCatalogCluster().getCatalog();
-    catalog.createTablespace(DEFAULT_TABLESPACE_NAME, CommonTestingUtil.getTestDir().toUri().toString());
-    catalog.createDatabase(DEFAULT_DATABASE_NAME, DEFAULT_TABLESPACE_NAME);
-    for (FunctionDesc funcDesc : TajoMaster.initBuiltinFunctions()) {
-      catalog.createFunction(funcDesc);
-    }
-
-    // TPC-H Schema for Complex Queries
-    String [] tpchTables = {
-        "part", "supplier", "partsupp", "nation", "region", "lineitem", "customer", "orders"
-    };
-    int [] tableVolumns = {
-        100, 200, 50, 5, 5, 800, 300, 100
-    };
-    tpch = new TPCH();
-    tpch.loadSchemas();
-    tpch.loadOutSchema();
-
-    for (int i = 0; i < tpchTables.length; i++) {
-      TableMeta m = CatalogUtil.newTableMeta(CatalogProtos.StoreType.CSV);
-      TableStats stats = new TableStats();
-      stats.setNumBytes(tableVolumns[i]);
-      TableDesc d = CatalogUtil.newTableDesc(tpchTables[i], tpch.getSchema(tpchTables[i]), m,
-          CommonTestingUtil.getTestDir());
-      d.setStats(stats);
-      catalog.createTable(d);
-    }
-    planner = new LogicalPlanner(catalog);
-    optimizer = new LogicalOptimizer(util.getConfiguration());
+    planner = new LogicalPlanner(util.getMiniCatalogCluster().getCatalog());
   }
 
   public static void tearDown() {

http://git-wip-us.apache.org/repos/asf/tajo/blob/7e31a320/tajo-core/src/test/java/org/apache/tajo/engine/query/TestGroupByQuery.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/test/java/org/apache/tajo/engine/query/TestGroupByQuery.java b/tajo-core/src/test/java/org/apache/tajo/engine/query/TestGroupByQuery.java
index 2b62c0e..ffb1915 100644
--- a/tajo-core/src/test/java/org/apache/tajo/engine/query/TestGroupByQuery.java
+++ b/tajo-core/src/test/java/org/apache/tajo/engine/query/TestGroupByQuery.java
@@ -167,6 +167,60 @@ public class TestGroupByQuery extends QueryTestCaseBase {
   }
 
   @Test
+  public final void testGroupByWithConstantKeys3() throws Exception {
+    // select
+    //   l_partkey as a,
+    //   timestamp '2014-07-07 04:28:31.561' as b,
+    //   '##' as c,
+    //   count(*) d
+    // from
+    //   lineitem
+    // group by
+    //  b, c;         <- b and c all are constant values.
+    ResultSet res = executeQuery();
+    assertResultSet(res);
+    cleanupQuery(res);
+  }
+
+  @Test
+  public final void testGroupByWithConstantKeys4() throws Exception {
+    //    select
+    //    'day',
+    //        l_orderkey,
+    //        count(*) as sum
+    //    from
+    //        lineitem
+    //    group by
+    //    'day',
+    //        l_orderkey
+    //    order by
+    //    'day',
+    //        l_orderkey;
+    ResultSet res = executeQuery();
+    assertResultSet(res);
+    cleanupQuery(res);
+  }
+
+  @Test
+  public final void testGroupByWithConstantKeys5() throws Exception {
+    //    select
+    //    'day',
+    //        l_orderkey,
+    //        count(*) as sum
+    //    from
+    //        lineitem
+    //    group by
+    //    'day',
+    //        l_orderkey
+    //    order by
+    //    'day',
+    //        l_orderkey;
+    ResultSet res = executeQuery();
+    assertResultSet(res);
+    cleanupQuery(res);
+  }
+
+  @Test
   public final void testDistinctAggregation1() throws Exception {
     // select l_orderkey, max(l_orderkey) as maximum, count(distinct l_linenumber) as unique_key from lineitem
     // group by l_orderkey;

http://git-wip-us.apache.org/repos/asf/tajo/blob/7e31a320/tajo-core/src/test/java/org/apache/tajo/engine/query/TestJoinQuery.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/test/java/org/apache/tajo/engine/query/TestJoinQuery.java b/tajo-core/src/test/java/org/apache/tajo/engine/query/TestJoinQuery.java
index 9501556..4afa9c3 100644
--- a/tajo-core/src/test/java/org/apache/tajo/engine/query/TestJoinQuery.java
+++ b/tajo-core/src/test/java/org/apache/tajo/engine/query/TestJoinQuery.java
@@ -239,6 +239,34 @@ public class TestJoinQuery extends QueryTestCaseBase {
   }
 
   @Test
+  public final void testLeftOuterJoinWithConstantExpr4() throws Exception {
+    // outer join with constant projections
+    //
+    // select
+    //   c_custkey,
+    //   orders.o_orderkey,
+    //   1 as key1
+    // from customer left outer join orders on c_custkey = o_orderkey and key1 = 1;
+    ResultSet res = executeQuery();
+    assertResultSet(res);
+    cleanupQuery(res);
+  }
+
+  @Test
+  public final void testLeftOuterJoinWithConstantExpr5() throws Exception {
+    // outer join with constant projections
+    //
+    // select
+    //   c_custkey,
+    //   orders.o_orderkey,
+    //   1 as key1
+    // from customer left outer join orders on c_custkey = o_orderkey and key1 = 1;
+    ResultSet res = executeQuery();
+    assertResultSet(res);
+    cleanupQuery(res);
+  }
+
+  @Test
   public final void testRightOuterJoin1() throws Exception {
     ResultSet res = executeQuery();
     assertResultSet(res);