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);