Repository: tajo Updated Branches: refs/heads/master 4eb871332 -> 72948b63a
TAJO-1499: Check the bind status when EvalNode::eval() is called. Closes #500 Project: http://git-wip-us.apache.org/repos/asf/tajo/repo Commit: http://git-wip-us.apache.org/repos/asf/tajo/commit/72948b63 Tree: http://git-wip-us.apache.org/repos/asf/tajo/tree/72948b63 Diff: http://git-wip-us.apache.org/repos/asf/tajo/diff/72948b63 Branch: refs/heads/master Commit: 72948b63a79cd8902381c3443699c887b2740491 Parents: 4eb8713 Author: Jihoon Son <[email protected]> Authored: Mon Apr 6 13:37:56 2015 +0900 Committer: Jihoon Son <[email protected]> Committed: Mon Apr 6 13:37:56 2015 +0900 ---------------------------------------------------------------------- CHANGES | 2 + .../planner/physical/ComparableVector.java | 35 +++--- .../org/apache/tajo/engine/utils/TupleUtil.java | 31 ------ .../apache/tajo/master/exec/QueryExecutor.java | 1 + .../apache/tajo/engine/eval/TestEvalTree.java | 107 ++++++++++++++----- .../tajo/engine/eval/TestEvalTreeUtil.java | 12 +-- .../org/apache/tajo/plan/LogicalPlanner.java | 1 + .../plan/expr/AggregationFunctionCallEval.java | 6 ++ .../apache/tajo/plan/expr/AlgebraicUtil.java | 6 +- .../tajo/plan/expr/BetweenPredicateEval.java | 5 +- .../org/apache/tajo/plan/expr/BinaryEval.java | 1 + .../org/apache/tajo/plan/expr/CaseWhenEval.java | 2 + .../org/apache/tajo/plan/expr/CastEval.java | 1 + .../org/apache/tajo/plan/expr/ConstEval.java | 1 + .../org/apache/tajo/plan/expr/EvalNode.java | 13 ++- .../org/apache/tajo/plan/expr/FieldEval.java | 5 +- .../org/apache/tajo/plan/expr/FunctionEval.java | 5 +- .../tajo/plan/expr/GeneralFunctionEval.java | 1 + .../java/org/apache/tajo/plan/expr/InEval.java | 3 + .../org/apache/tajo/plan/expr/IsNullEval.java | 1 + .../java/org/apache/tajo/plan/expr/NotEval.java | 1 + .../plan/expr/PatternMatchPredicateEval.java | 6 +- .../apache/tajo/plan/expr/RowConstantEval.java | 1 + .../org/apache/tajo/plan/expr/SignedEval.java | 1 + .../org/apache/tajo/plan/expr/UnaryEval.java | 1 + .../tajo/plan/expr/WindowFunctionEval.java | 3 + 26 files changed, 165 insertions(+), 87 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tajo/blob/72948b63/CHANGES ---------------------------------------------------------------------- diff --git a/CHANGES b/CHANGES index 7ea0b5e..90fa245 100644 --- a/CHANGES +++ b/CHANGES @@ -11,6 +11,8 @@ Release 0.11.0 - unreleased IMPROVEMENT + TAJO-1499: Check the bind status when EvalNode::eval() is called. (jihoon) + TAJO-1400: Add TajoStatement::setMaxRows method support. (Contributed by YeonSu Han, Committed by jihoon) http://git-wip-us.apache.org/repos/asf/tajo/blob/72948b63/tajo-core/src/main/java/org/apache/tajo/engine/planner/physical/ComparableVector.java ---------------------------------------------------------------------- diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/planner/physical/ComparableVector.java b/tajo-core/src/main/java/org/apache/tajo/engine/planner/physical/ComparableVector.java index 39b8c8a..9940608 100644 --- a/tajo-core/src/main/java/org/apache/tajo/engine/planner/physical/ComparableVector.java +++ b/tajo-core/src/main/java/org/apache/tajo/engine/planner/physical/ComparableVector.java @@ -225,24 +225,27 @@ public class ComparableVector { @Override public boolean equals(Object obj) { - ComparableTuple other = (ComparableTuple)obj; - for (int i = 0; i < keys.length; i++) { - final boolean n1 = keys[i] == null; - final boolean n2 = other.keys[i] == null; - if (n1 && n2) { - continue; - } - if (n1 ^ n2) { - return false; - } - switch (keyTypes[i]) { - case TEXT: - case CHAR: - case BLOB: if (!Arrays.equals((byte[])keys[i], (byte[])other.keys[i])) return false; continue; - default: if (!keys[i].equals(other.keys[i])) return false; continue; + if (obj instanceof ComparableTuple) { + ComparableTuple other = (ComparableTuple)obj; + for (int i = 0; i < keys.length; i++) { + final boolean n1 = keys[i] == null; + final boolean n2 = other.keys[i] == null; + if (n1 && n2) { + continue; + } + if (n1 ^ n2) { + return false; + } + switch (keyTypes[i]) { + case TEXT: + case CHAR: + case BLOB: if (!Arrays.equals((byte[])keys[i], (byte[])other.keys[i])) return false; continue; + default: if (!keys[i].equals(other.keys[i])) return false; continue; + } } + return true; } - return true; + return false; } public boolean equals(Tuple tuple) { http://git-wip-us.apache.org/repos/asf/tajo/blob/72948b63/tajo-core/src/main/java/org/apache/tajo/engine/utils/TupleUtil.java ---------------------------------------------------------------------- diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/utils/TupleUtil.java b/tajo-core/src/main/java/org/apache/tajo/engine/utils/TupleUtil.java index 6b2c37c..3a0a1c7 100644 --- a/tajo-core/src/main/java/org/apache/tajo/engine/utils/TupleUtil.java +++ b/tajo-core/src/main/java/org/apache/tajo/engine/utils/TupleUtil.java @@ -193,35 +193,4 @@ public class TupleUtil { } return aTuple; } - - @SuppressWarnings("unused") - public static Collection<Tuple> filterTuple(Schema schema, Collection<Tuple> tupleBlock, EvalNode filterCondition) { - TupleBlockFilterScanner filter = new TupleBlockFilterScanner(schema, tupleBlock, filterCondition); - return filter.nextBlock(); - } - - private static class TupleBlockFilterScanner { - private EvalNode qual; - private Iterator<Tuple> iterator; - private Schema schema; - - public TupleBlockFilterScanner(Schema schema, Collection<Tuple> tuples, EvalNode qual) { - this.schema = schema; - this.qual = qual; - this.iterator = tuples.iterator(); - } - - public List<Tuple> nextBlock() { - List<Tuple> results = Lists.newArrayList(); - - Tuple tuple; - while (iterator.hasNext()) { - tuple = iterator.next(); - if (qual.eval(tuple).isTrue()) { - results.add(tuple); - } - } - return results; - } - } } http://git-wip-us.apache.org/repos/asf/tajo/blob/72948b63/tajo-core/src/main/java/org/apache/tajo/master/exec/QueryExecutor.java ---------------------------------------------------------------------- diff --git a/tajo-core/src/main/java/org/apache/tajo/master/exec/QueryExecutor.java b/tajo-core/src/main/java/org/apache/tajo/master/exec/QueryExecutor.java index cec1125..2eb3c5f 100644 --- a/tajo-core/src/main/java/org/apache/tajo/master/exec/QueryExecutor.java +++ b/tajo-core/src/main/java/org/apache/tajo/master/exec/QueryExecutor.java @@ -274,6 +274,7 @@ public class QueryExecutor { final Tuple outTuple = new VTuple(targets.length); for (int i = 0; i < targets.length; i++) { EvalNode eval = targets[i].getEvalTree(); + eval.bind(null); outTuple.put(i, eval.eval(null)); } boolean isInsert = rootNode.getChild() != null && rootNode.getChild().getType() == NodeType.INSERT; http://git-wip-us.apache.org/repos/asf/tajo/blob/72948b63/tajo-core/src/test/java/org/apache/tajo/engine/eval/TestEvalTree.java ---------------------------------------------------------------------- diff --git a/tajo-core/src/test/java/org/apache/tajo/engine/eval/TestEvalTree.java b/tajo-core/src/test/java/org/apache/tajo/engine/eval/TestEvalTree.java index f03988b..a2d0598 100644 --- a/tajo-core/src/test/java/org/apache/tajo/engine/eval/TestEvalTree.java +++ b/tajo-core/src/test/java/org/apache/tajo/engine/eval/TestEvalTree.java @@ -19,7 +19,9 @@ package org.apache.tajo.engine.eval; import org.apache.tajo.catalog.CatalogUtil; +import org.apache.tajo.catalog.Column; import org.apache.tajo.catalog.Schema; +import org.apache.tajo.common.TajoDataTypes; import org.apache.tajo.common.TajoDataTypes.DataType; import org.apache.tajo.datum.Datum; import org.apache.tajo.datum.DatumFactory; @@ -31,6 +33,7 @@ import org.junit.Test; import static org.apache.tajo.common.TajoDataTypes.Type.*; import static org.junit.Assert.*; +import static org.junit.Assert.fail; public class TestEvalTree extends ExprTestBase { @Test @@ -79,6 +82,7 @@ public class TestEvalTree extends ExprTestBase { @Override public Datum eval(Tuple tuple) { + super.eval(tuple); return DatumFactory.createBool(true); } @@ -111,6 +115,7 @@ public class TestEvalTree extends ExprTestBase { @Override public Datum eval(Tuple tuple) { + super.eval(tuple); return DatumFactory.createBool(false); } @@ -156,15 +161,19 @@ public class TestEvalTree extends ExprTestBase { MockFalseExpr falseExpr = new MockFalseExpr(); BinaryEval andExpr = new BinaryEval(EvalType.AND, trueExpr, trueExpr); + andExpr.bind(null); assertTrue(andExpr.eval(null).asBool()); andExpr = new BinaryEval(EvalType.AND, falseExpr, trueExpr); + andExpr.bind(null); assertFalse(andExpr.eval(null).asBool()); andExpr = new BinaryEval(EvalType.AND, trueExpr, falseExpr); + andExpr.bind(null); assertFalse(andExpr.eval(null).asBool()); andExpr = new BinaryEval(EvalType.AND, falseExpr, falseExpr); + andExpr.bind(null); assertFalse(andExpr.eval(null).asBool()); } @@ -174,15 +183,19 @@ public class TestEvalTree extends ExprTestBase { MockFalseExpr falseExpr = new MockFalseExpr(); BinaryEval orExpr = new BinaryEval(EvalType.OR, trueExpr, trueExpr); + orExpr.bind(null); assertTrue(orExpr.eval(null).asBool()); orExpr = new BinaryEval(EvalType.OR, falseExpr, trueExpr); + orExpr.bind(null); assertTrue(orExpr.eval(null).asBool()); orExpr = new BinaryEval(EvalType.OR, trueExpr, falseExpr); + orExpr.bind(null); assertTrue(orExpr.eval(null).asBool()); orExpr = new BinaryEval(EvalType.OR, falseExpr, falseExpr); + orExpr.bind(null); assertFalse(orExpr.eval(null).asBool()); } @@ -196,41 +209,41 @@ public class TestEvalTree extends ExprTestBase { e1 = new ConstEval(DatumFactory.createInt4(9)); e2 = new ConstEval(DatumFactory.createInt4(34)); expr = new BinaryEval(EvalType.LTH, e1, e2); - assertTrue(expr.eval(null).asBool()); + assertTrue(expr.bind(null).eval(null).asBool()); expr = new BinaryEval(EvalType.LEQ, e1, e2); - assertTrue(expr.eval(null).asBool()); + assertTrue(expr.bind(null).eval(null).asBool()); expr = new BinaryEval(EvalType.LTH, e2, e1); - assertFalse(expr.eval(null).asBool()); + assertFalse(expr.bind(null).eval(null).asBool()); expr = new BinaryEval(EvalType.LEQ, e2, e1); - assertFalse(expr.eval(null).asBool()); + assertFalse(expr.bind(null).eval(null).asBool()); expr = new BinaryEval(EvalType.GTH, e2, e1); - assertTrue(expr.eval(null).asBool()); + assertTrue(expr.bind(null).eval(null).asBool()); expr = new BinaryEval(EvalType.GEQ, e2, e1); - assertTrue(expr.eval(null).asBool()); + assertTrue(expr.bind(null).eval(null).asBool()); expr = new BinaryEval(EvalType.GTH, e1, e2); - assertFalse(expr.eval(null).asBool()); + assertFalse(expr.bind(null).eval(null).asBool()); expr = new BinaryEval(EvalType.GEQ, e1, e2); - assertFalse(expr.eval(null).asBool()); + assertFalse(expr.bind(null).eval(null).asBool()); BinaryEval plus = new BinaryEval(EvalType.PLUS, e1, e2); expr = new BinaryEval(EvalType.LTH, e1, plus); - assertTrue(expr.eval(null).asBool()); + assertTrue(expr.bind(null).eval(null).asBool()); expr = new BinaryEval(EvalType.LEQ, e1, plus); - assertTrue(expr.eval(null).asBool()); + assertTrue(expr.bind(null).eval(null).asBool()); expr = new BinaryEval(EvalType.LTH, plus, e1); - assertFalse(expr.eval(null).asBool()); + assertFalse(expr.bind(null).eval(null).asBool()); expr = new BinaryEval(EvalType.LEQ, plus, e1); - assertFalse(expr.eval(null).asBool()); + assertFalse(expr.bind(null).eval(null).asBool()); expr = new BinaryEval(EvalType.GTH, plus, e1); - assertTrue(expr.eval(null).asBool()); + assertTrue(expr.bind(null).eval(null).asBool()); expr = new BinaryEval(EvalType.GEQ, plus, e1); - assertTrue(expr.eval(null).asBool()); + assertTrue(expr.bind(null).eval(null).asBool()); expr = new BinaryEval(EvalType.GTH, e1, plus); - assertFalse(expr.eval(null).asBool()); + assertFalse(expr.bind(null).eval(null).asBool()); expr = new BinaryEval(EvalType.GEQ, e1, plus); - assertFalse(expr.eval(null).asBool()); + assertFalse(expr.bind(null).eval(null).asBool()); } @Test @@ -243,28 +256,28 @@ public class TestEvalTree extends ExprTestBase { e1 = new ConstEval(DatumFactory.createInt4(9)); e2 = new ConstEval(DatumFactory.createInt4(34)); BinaryEval expr = new BinaryEval(EvalType.PLUS, e1, e2); - assertEquals(expr.eval(null).asInt4(), 43); + assertEquals(expr.bind(null).eval(null).asInt4(), 43); assertCloneEqual(expr); // MINUS e1 = new ConstEval(DatumFactory.createInt4(5)); e2 = new ConstEval(DatumFactory.createInt4(2)); expr = new BinaryEval(EvalType.MINUS, e1, e2); - assertEquals(expr.eval(null).asInt4(), 3); + assertEquals(expr.bind(null).eval(null).asInt4(), 3); assertCloneEqual(expr); // MULTIPLY e1 = new ConstEval(DatumFactory.createInt4(5)); e2 = new ConstEval(DatumFactory.createInt4(2)); expr = new BinaryEval(EvalType.MULTIPLY, e1, e2); - assertEquals(expr.eval(null).asInt4(), 10); + assertEquals(expr.bind(null).eval(null).asInt4(), 10); assertCloneEqual(expr); // DIVIDE e1 = new ConstEval(DatumFactory.createInt4(10)); e2 = new ConstEval(DatumFactory.createInt4(5)); expr = new BinaryEval(EvalType.DIVIDE, e1, e2); - assertEquals(expr.eval(null).asInt4(), 2); + assertEquals(expr.bind(null).eval(null).asInt4(), 2); assertCloneEqual(expr); } @@ -280,7 +293,7 @@ public class TestEvalTree extends ExprTestBase { assertEquals(CatalogUtil.newSimpleDataType(INT4), expr.getValueType()); expr = new BinaryEval(EvalType.LTH, e1, e2); - assertTrue(expr.eval(null).asBool()); + assertTrue(expr.bind(null).eval(null).asBool()); assertEquals(CatalogUtil.newSimpleDataType(BOOLEAN), expr.getValueType()); e1 = new ConstEval(DatumFactory.createFloat8(9.3)); @@ -350,11 +363,57 @@ public class TestEvalTree extends ExprTestBase { assertEquals(e3.getType(), eval.getLeftExpr().getType()); assertEquals(plus3.getType(), eval.getRightExpr().getType()); assertEquals(plus3.getLeftExpr(), ((BinaryEval)eval.getRightExpr()).getLeftExpr()); - assertEquals(plus3.getRightExpr(), ((BinaryEval)eval.getRightExpr()).getRightExpr()); + assertEquals(plus3.getRightExpr(), ((BinaryEval) eval.getRightExpr()).getRightExpr()); assertEquals(plus2.getLeftExpr(), ((BinaryEval)((BinaryEval)eval.getRightExpr()).getLeftExpr()).getLeftExpr()); assertEquals(plus2.getRightExpr(), ((BinaryEval)((BinaryEval)eval.getRightExpr()).getLeftExpr()).getRightExpr()); - assertEquals(plus1.getLeftExpr(), ((BinaryEval)((BinaryEval)eval.getRightExpr()).getRightExpr()).getLeftExpr()); - assertEquals(plus1.getRightExpr(), ((BinaryEval)((BinaryEval)eval.getRightExpr()).getRightExpr()).getRightExpr()); + assertEquals(plus1.getLeftExpr(), ((BinaryEval) ((BinaryEval) eval.getRightExpr()).getRightExpr()).getLeftExpr()); + assertEquals(plus1.getRightExpr(), ((BinaryEval) ((BinaryEval) eval.getRightExpr()).getRightExpr()).getRightExpr()); + } + + @Test + public final void testBindCheck() { + ConstEval e1; + ConstEval e2; + BinaryEval binEval; + + // Constant + e1 = new ConstEval(DatumFactory.createInt4(9)); + e2 = new ConstEval(DatumFactory.createInt4(34)); + binEval = new BinaryEval(EvalType.LTH, e1, e2); + try { + binEval.eval(null); + fail("EvalNode is not binded"); + } catch (IllegalStateException e) { + assertTrue(binEval.bind(null).eval(null).asBool()); + } + + CaseWhenEval caseWhenEval = new CaseWhenEval(); + caseWhenEval.addIfCond(new CaseWhenEval.IfThenEval(binEval, new ConstEval(DatumFactory.createInt4(1)))); + try { + caseWhenEval.eval(null); + fail("EvalNode is not binded"); + } catch (IllegalStateException e) { + assertEquals(caseWhenEval.bind(null).eval(null).asInt4(), 1); + } + + Schema schema = new Schema(new Column[]{new Column("test", TajoDataTypes.Type.INT4)}); + Tuple tuple = new VTuple(new Datum[]{DatumFactory.createText("aaa")}); + RegexPredicateEval regexEval = new RegexPredicateEval(false, new FieldEval("test", + CatalogUtil.newSimpleDataType(TajoDataTypes.Type.INT4)), new ConstEval(DatumFactory.createText("a*")), false); + try { + regexEval.eval(null); + fail("EvalNode is not binded"); + } catch (IllegalStateException e) { + assertEquals(regexEval.bind(schema).eval(tuple).asBool(), true); + } + + RowConstantEval rowConstantEval = new RowConstantEval(new Datum[]{}); + try { + rowConstantEval.eval(null); + fail("EvalNode is not binded"); + } catch (IllegalStateException e) { + assertEquals(rowConstantEval.bind(null).eval(null).isNull(), true); + } } private void assertCloneEqual(EvalNode eval) throws CloneNotSupportedException { http://git-wip-us.apache.org/repos/asf/tajo/blob/72948b63/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 61c55e1..e23a34b 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 @@ -265,12 +265,12 @@ public class TestEvalTreeUtil { FieldEval field = first.getLeftExpr(); assertEquals(col1, field.getColumnRef()); assertEquals(EvalType.LTH, first.getType()); - assertEquals(10, first.getRightExpr().eval(null).asInt4()); + assertEquals(10, first.getRightExpr().bind(null).eval(null).asInt4()); field = second.getRightExpr(); assertEquals(col1, field.getColumnRef()); assertEquals(EvalType.LTH, second.getType()); - assertEquals(4, second.getLeftExpr().eval(null).asInt4()); + assertEquals(4, second.getLeftExpr().bind(null).eval(null).asInt4()); } @Test @@ -304,10 +304,10 @@ public class TestEvalTreeUtil { Target [] targets = getRawTargets(QUERIES[0]); EvalNode node = AlgebraicUtil.eliminateConstantExprs(targets[0].getEvalTree()); assertEquals(EvalType.CONST, node.getType()); - assertEquals(7, node.eval(null).asInt4()); + assertEquals(7, node.bind(null).eval(null).asInt4()); node = AlgebraicUtil.eliminateConstantExprs(targets[1].getEvalTree()); assertEquals(EvalType.CONST, node.getType()); - assertTrue(7.0d == node.eval(null).asFloat8()); + assertTrue(7.0d == node.bind(null).eval(null).asFloat8()); Expr expr = analyzer.parse(QUERIES[1]); LogicalPlan plan = planner.createPlan(defaultContext, expr, true); @@ -335,7 +335,7 @@ public class TestEvalTreeUtil { assertEquals(EvalType.GTH, transposed.getType()); FieldEval field = transposed.getLeftExpr(); assertEquals(col1, field.getColumnRef()); - assertEquals(1, transposed.getRightExpr().eval(null).asInt4()); + assertEquals(1, transposed.getRightExpr().bind(null).eval(null).asInt4()); node = getRootSelection(QUERIES[4]); // we expect that score < 3 @@ -343,7 +343,7 @@ public class TestEvalTreeUtil { assertEquals(EvalType.LTH, transposed.getType()); field = transposed.getLeftExpr(); assertEquals(col1, field.getColumnRef()); - assertEquals(2, transposed.getRightExpr().eval(null).asInt4()); + assertEquals(2, transposed.getRightExpr().bind(null).eval(null).asInt4()); } @Test http://git-wip-us.apache.org/repos/asf/tajo/blob/72948b63/tajo-plan/src/main/java/org/apache/tajo/plan/LogicalPlanner.java ---------------------------------------------------------------------- diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/LogicalPlanner.java b/tajo-plan/src/main/java/org/apache/tajo/plan/LogicalPlanner.java index d6a04a6..d7c631b 100644 --- a/tajo-plan/src/main/java/org/apache/tajo/plan/LogicalPlanner.java +++ b/tajo-plan/src/main/java/org/apache/tajo/plan/LogicalPlanner.java @@ -810,6 +810,7 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex limitNode.setInSchema(child.getOutSchema()); limitNode.setOutSchema(child.getOutSchema()); + firstFetNum.bind(null); limitNode.setFetchFirst(firstFetNum.eval(null).asInt8()); return limitNode; http://git-wip-us.apache.org/repos/asf/tajo/blob/72948b63/tajo-plan/src/main/java/org/apache/tajo/plan/expr/AggregationFunctionCallEval.java ---------------------------------------------------------------------- diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/expr/AggregationFunctionCallEval.java b/tajo-plan/src/main/java/org/apache/tajo/plan/expr/AggregationFunctionCallEval.java index 984d18c..5549e2e 100644 --- a/tajo-plan/src/main/java/org/apache/tajo/plan/expr/AggregationFunctionCallEval.java +++ b/tajo-plan/src/main/java/org/apache/tajo/plan/expr/AggregationFunctionCallEval.java @@ -50,6 +50,9 @@ public class AggregationFunctionCallEval extends FunctionEval implements Cloneab } public void merge(FunctionContext context, Tuple tuple) { + if (!isBinded) { + throw new IllegalStateException("bind() must be called before merge()"); + } mergeParam(context, evalParams(tuple)); } @@ -68,6 +71,9 @@ public class AggregationFunctionCallEval extends FunctionEval implements Cloneab } public Datum terminate(FunctionContext context) { + if (!isBinded) { + throw new IllegalStateException("bind() must be called before terminate()"); + } if (!finalPhase) { return instance.getPartialResult(context); } else { http://git-wip-us.apache.org/repos/asf/tajo/blob/72948b63/tajo-plan/src/main/java/org/apache/tajo/plan/expr/AlgebraicUtil.java ---------------------------------------------------------------------- diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/expr/AlgebraicUtil.java b/tajo-plan/src/main/java/org/apache/tajo/plan/expr/AlgebraicUtil.java index f697968..fb05f33 100644 --- a/tajo-plan/src/main/java/org/apache/tajo/plan/expr/AlgebraicUtil.java +++ b/tajo-plan/src/main/java/org/apache/tajo/plan/expr/AlgebraicUtil.java @@ -149,7 +149,7 @@ public class AlgebraicUtil { } if (lhs.getType() == EvalType.CONST && rhs.getType() == EvalType.CONST) { - return new ConstEval(binaryEval.eval(null)); + return new ConstEval(binaryEval.bind(null).eval(null)); } return binaryEval; @@ -162,7 +162,7 @@ public class AlgebraicUtil { stack.pop(); if (child.getType() == EvalType.CONST) { - return new ConstEval(unaryEval.eval(null)); + return new ConstEval(unaryEval.bind(null).eval(null)); } return unaryEval; @@ -184,7 +184,7 @@ public class AlgebraicUtil { } if (constantOfAllDescendents && evalNode.getType() == EvalType.FUNCTION) { - return new ConstEval(evalNode.eval(null)); + return new ConstEval(evalNode.bind(null).eval(null)); } else { return evalNode; } http://git-wip-us.apache.org/repos/asf/tajo/blob/72948b63/tajo-plan/src/main/java/org/apache/tajo/plan/expr/BetweenPredicateEval.java ---------------------------------------------------------------------- diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/expr/BetweenPredicateEval.java b/tajo-plan/src/main/java/org/apache/tajo/plan/expr/BetweenPredicateEval.java index 3969f63..2db4368 100644 --- a/tajo-plan/src/main/java/org/apache/tajo/plan/expr/BetweenPredicateEval.java +++ b/tajo-plan/src/main/java/org/apache/tajo/plan/expr/BetweenPredicateEval.java @@ -227,7 +227,8 @@ public class BetweenPredicateEval extends EvalNode implements Cloneable { } @Override - public void bind(Schema schema) { + public EvalNode bind(Schema schema) { + super.bind(schema); if (begin.getType() == EvalType.CONST && end.getType() == EvalType.CONST) { Datum beginValue = ((ConstEval)begin).getValue(); Datum endValue = ((ConstEval)end).getValue(); @@ -245,11 +246,13 @@ public class BetweenPredicateEval extends EvalNode implements Cloneable { } } checker.bind(schema); + return this; } @Override @SuppressWarnings("unchecked") public Datum eval(Tuple tuple) { + super.eval(tuple); return checker.eval(tuple); } http://git-wip-us.apache.org/repos/asf/tajo/blob/72948b63/tajo-plan/src/main/java/org/apache/tajo/plan/expr/BinaryEval.java ---------------------------------------------------------------------- diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/expr/BinaryEval.java b/tajo-plan/src/main/java/org/apache/tajo/plan/expr/BinaryEval.java index e189a36..531cb9f 100644 --- a/tajo-plan/src/main/java/org/apache/tajo/plan/expr/BinaryEval.java +++ b/tajo-plan/src/main/java/org/apache/tajo/plan/expr/BinaryEval.java @@ -119,6 +119,7 @@ public class BinaryEval extends EvalNode implements Cloneable { @Override @SuppressWarnings("unchecked") public Datum eval(Tuple tuple) { + super.eval(tuple); Datum lhs = leftExpr.eval(tuple); Datum rhs = rightExpr.eval(tuple); http://git-wip-us.apache.org/repos/asf/tajo/blob/72948b63/tajo-plan/src/main/java/org/apache/tajo/plan/expr/CaseWhenEval.java ---------------------------------------------------------------------- diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/expr/CaseWhenEval.java b/tajo-plan/src/main/java/org/apache/tajo/plan/expr/CaseWhenEval.java index c25ad45..2f40974 100644 --- a/tajo-plan/src/main/java/org/apache/tajo/plan/expr/CaseWhenEval.java +++ b/tajo-plan/src/main/java/org/apache/tajo/plan/expr/CaseWhenEval.java @@ -107,6 +107,7 @@ public class CaseWhenEval extends EvalNode implements GsonObject { @Override @SuppressWarnings("unchecked") public Datum eval(Tuple tuple) { + super.eval(tuple); for (IfThenEval eval : whens) { if (eval.checkIfCondition(tuple)) { return eval.eval(tuple); @@ -233,6 +234,7 @@ public class CaseWhenEval extends EvalNode implements GsonObject { @Override @SuppressWarnings("unchecked") public Datum eval(Tuple tuple) { + super.eval(tuple); return result.eval(tuple); } http://git-wip-us.apache.org/repos/asf/tajo/blob/72948b63/tajo-plan/src/main/java/org/apache/tajo/plan/expr/CastEval.java ---------------------------------------------------------------------- diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/expr/CastEval.java b/tajo-plan/src/main/java/org/apache/tajo/plan/expr/CastEval.java index 5a26593..f174b79 100644 --- a/tajo-plan/src/main/java/org/apache/tajo/plan/expr/CastEval.java +++ b/tajo-plan/src/main/java/org/apache/tajo/plan/expr/CastEval.java @@ -70,6 +70,7 @@ public class CastEval extends UnaryEval { @Override @SuppressWarnings("unchecked") public Datum eval(Tuple tuple) { + super.eval(tuple); Datum operandDatum = child.eval(tuple); if (operandDatum.isNull()) { return operandDatum; http://git-wip-us.apache.org/repos/asf/tajo/blob/72948b63/tajo-plan/src/main/java/org/apache/tajo/plan/expr/ConstEval.java ---------------------------------------------------------------------- diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/expr/ConstEval.java b/tajo-plan/src/main/java/org/apache/tajo/plan/expr/ConstEval.java index 82e4e8e..ff964e6 100644 --- a/tajo-plan/src/main/java/org/apache/tajo/plan/expr/ConstEval.java +++ b/tajo-plan/src/main/java/org/apache/tajo/plan/expr/ConstEval.java @@ -45,6 +45,7 @@ public class ConstEval extends EvalNode implements Comparable<ConstEval>, Clonea @Override @SuppressWarnings("unchecked") public Datum eval(Tuple tuple) { + super.eval(tuple); return datum; } http://git-wip-us.apache.org/repos/asf/tajo/blob/72948b63/tajo-plan/src/main/java/org/apache/tajo/plan/expr/EvalNode.java ---------------------------------------------------------------------- diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/expr/EvalNode.java b/tajo-plan/src/main/java/org/apache/tajo/plan/expr/EvalNode.java index f57302a..154b0fd 100644 --- a/tajo-plan/src/main/java/org/apache/tajo/plan/expr/EvalNode.java +++ b/tajo-plan/src/main/java/org/apache/tajo/plan/expr/EvalNode.java @@ -35,6 +35,7 @@ import org.apache.tajo.storage.Tuple; */ public abstract class EvalNode implements Cloneable, GsonObject, ProtoObject<PlanProto.EvalNodeTree> { @Expose protected EvalType type; + protected boolean isBinded = false; public EvalNode() { } @@ -60,13 +61,20 @@ public abstract class EvalNode implements Cloneable, GsonObject, ProtoObject<Pla return PlanGsonHelper.toJson(this, EvalNode.class); } - public void bind(Schema schema) { + public EvalNode bind(Schema schema) { for (int i = 0; i < childNum(); i++) { getChild(i).bind(schema); } + isBinded = true; + return this; } - public abstract <T extends Datum> T eval(Tuple tuple); + public <T extends Datum> T eval(Tuple tuple) { + if (!isBinded) { + throw new IllegalStateException("bind() must be called before eval()"); + } + return null; + } @Deprecated public abstract void preOrder(EvalNodeVisitor visitor); @@ -78,6 +86,7 @@ public abstract class EvalNode implements Cloneable, GsonObject, ProtoObject<Pla public Object clone() throws CloneNotSupportedException { EvalNode evalNode = (EvalNode) super.clone(); evalNode.type = type; + evalNode.isBinded = isBinded; return evalNode; } http://git-wip-us.apache.org/repos/asf/tajo/blob/72948b63/tajo-plan/src/main/java/org/apache/tajo/plan/expr/FieldEval.java ---------------------------------------------------------------------- diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/expr/FieldEval.java b/tajo-plan/src/main/java/org/apache/tajo/plan/expr/FieldEval.java index 11b3b6d..83d00b9 100644 --- a/tajo-plan/src/main/java/org/apache/tajo/plan/expr/FieldEval.java +++ b/tajo-plan/src/main/java/org/apache/tajo/plan/expr/FieldEval.java @@ -40,7 +40,8 @@ public class FieldEval extends EvalNode implements Cloneable { } @Override - public void bind(Schema schema) { + public EvalNode bind(Schema schema) { + super.bind(schema); // TODO - column namespace should be improved to simplify name handling and resolving. if (column.hasQualifier()) { fieldId = schema.getColumnId(column.getQualifiedName()); @@ -50,11 +51,13 @@ public class FieldEval extends EvalNode implements Cloneable { if (fieldId == -1) { throw new IllegalStateException("No Such Column Reference: " + column + ", schema: " + schema); } + return this; } @Override @SuppressWarnings("unchecked") public Datum eval(Tuple tuple) { + super.eval(tuple); return tuple.get(fieldId); } http://git-wip-us.apache.org/repos/asf/tajo/blob/72948b63/tajo-plan/src/main/java/org/apache/tajo/plan/expr/FunctionEval.java ---------------------------------------------------------------------- diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/expr/FunctionEval.java b/tajo-plan/src/main/java/org/apache/tajo/plan/expr/FunctionEval.java index 0c60c8d..4ff7548 100644 --- a/tajo-plan/src/main/java/org/apache/tajo/plan/expr/FunctionEval.java +++ b/tajo-plan/src/main/java/org/apache/tajo/plan/expr/FunctionEval.java @@ -33,7 +33,7 @@ import static org.apache.tajo.catalog.proto.CatalogProtos.FunctionType.DISTINCT_ import static org.apache.tajo.catalog.proto.CatalogProtos.FunctionType.DISTINCT_UDA; public abstract class FunctionEval extends EvalNode implements Cloneable { - public static enum ParamType { + public enum ParamType { CONSTANT, VARIABLE, NULL } @@ -49,9 +49,10 @@ public abstract class FunctionEval extends EvalNode implements Cloneable { } @Override - public void bind(Schema schema) { + public EvalNode bind(Schema schema) { super.bind(schema); this.params = new VTuple(argEvals.length); + return this; } protected final Tuple evalParams(Tuple tuple) { http://git-wip-us.apache.org/repos/asf/tajo/blob/72948b63/tajo-plan/src/main/java/org/apache/tajo/plan/expr/GeneralFunctionEval.java ---------------------------------------------------------------------- diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/expr/GeneralFunctionEval.java b/tajo-plan/src/main/java/org/apache/tajo/plan/expr/GeneralFunctionEval.java index 747e8ba..2ce7850 100644 --- a/tajo-plan/src/main/java/org/apache/tajo/plan/expr/GeneralFunctionEval.java +++ b/tajo-plan/src/main/java/org/apache/tajo/plan/expr/GeneralFunctionEval.java @@ -42,6 +42,7 @@ public class GeneralFunctionEval extends FunctionEval { @Override @SuppressWarnings("unchecked") public Datum eval(Tuple tuple) { + super.eval(tuple); return instance.eval(evalParams(tuple)); } http://git-wip-us.apache.org/repos/asf/tajo/blob/72948b63/tajo-plan/src/main/java/org/apache/tajo/plan/expr/InEval.java ---------------------------------------------------------------------- diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/expr/InEval.java b/tajo-plan/src/main/java/org/apache/tajo/plan/expr/InEval.java index c222bef..c968bda 100644 --- a/tajo-plan/src/main/java/org/apache/tajo/plan/expr/InEval.java +++ b/tajo-plan/src/main/java/org/apache/tajo/plan/expr/InEval.java @@ -58,6 +58,9 @@ public class InEval extends BinaryEval { @Override public Datum eval(Tuple tuple) { + if (!isBinded) { + throw new IllegalStateException("bind() must be called before eval()"); + } if (values == null) { values = Sets.newHashSet(((RowConstantEval)rightExpr).getValues()); } http://git-wip-us.apache.org/repos/asf/tajo/blob/72948b63/tajo-plan/src/main/java/org/apache/tajo/plan/expr/IsNullEval.java ---------------------------------------------------------------------- diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/expr/IsNullEval.java b/tajo-plan/src/main/java/org/apache/tajo/plan/expr/IsNullEval.java index 496f64d..72b36eb 100644 --- a/tajo-plan/src/main/java/org/apache/tajo/plan/expr/IsNullEval.java +++ b/tajo-plan/src/main/java/org/apache/tajo/plan/expr/IsNullEval.java @@ -58,6 +58,7 @@ public class IsNullEval extends UnaryEval { @Override @SuppressWarnings("unchecked") public Datum eval(Tuple tuple) { + super.eval(tuple); boolean isNull = child.eval(tuple).isNull(); return DatumFactory.createBool(isNot ^ isNull); } http://git-wip-us.apache.org/repos/asf/tajo/blob/72948b63/tajo-plan/src/main/java/org/apache/tajo/plan/expr/NotEval.java ---------------------------------------------------------------------- diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/expr/NotEval.java b/tajo-plan/src/main/java/org/apache/tajo/plan/expr/NotEval.java index ccec0fe..088f3a5 100644 --- a/tajo-plan/src/main/java/org/apache/tajo/plan/expr/NotEval.java +++ b/tajo-plan/src/main/java/org/apache/tajo/plan/expr/NotEval.java @@ -45,6 +45,7 @@ public class NotEval extends UnaryEval implements Cloneable { @Override @SuppressWarnings("unchecked") public Datum eval(Tuple tuple) { + super.eval(tuple); Datum datum = child.eval(tuple); return !datum.isNull() ? DatumFactory.createBool(!datum.asBool()) : datum; } http://git-wip-us.apache.org/repos/asf/tajo/blob/72948b63/tajo-plan/src/main/java/org/apache/tajo/plan/expr/PatternMatchPredicateEval.java ---------------------------------------------------------------------- diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/expr/PatternMatchPredicateEval.java b/tajo-plan/src/main/java/org/apache/tajo/plan/expr/PatternMatchPredicateEval.java index a5d055d..6faa667 100644 --- a/tajo-plan/src/main/java/org/apache/tajo/plan/expr/PatternMatchPredicateEval.java +++ b/tajo-plan/src/main/java/org/apache/tajo/plan/expr/PatternMatchPredicateEval.java @@ -74,13 +74,17 @@ public abstract class PatternMatchPredicateEval extends BinaryEval { } @Override - public void bind(Schema schema) { + public EvalNode bind(Schema schema) { super.bind(schema); compile(pattern); + return this; } @Override public Datum eval(Tuple tuple) { + if (!isBinded) { + throw new IllegalStateException("bind() must be called before eval()"); + } Datum predicand = leftExpr.eval(tuple); if (predicand.isNull()) { return NullDatum.get(); http://git-wip-us.apache.org/repos/asf/tajo/blob/72948b63/tajo-plan/src/main/java/org/apache/tajo/plan/expr/RowConstantEval.java ---------------------------------------------------------------------- diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/expr/RowConstantEval.java b/tajo-plan/src/main/java/org/apache/tajo/plan/expr/RowConstantEval.java index b81c352..153a150 100644 --- a/tajo-plan/src/main/java/org/apache/tajo/plan/expr/RowConstantEval.java +++ b/tajo-plan/src/main/java/org/apache/tajo/plan/expr/RowConstantEval.java @@ -61,6 +61,7 @@ public class RowConstantEval extends EvalNode { @Override @SuppressWarnings("unchecked") public Datum eval(Tuple tuple) { + super.eval(tuple); return NullDatum.get(); } http://git-wip-us.apache.org/repos/asf/tajo/blob/72948b63/tajo-plan/src/main/java/org/apache/tajo/plan/expr/SignedEval.java ---------------------------------------------------------------------- diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/expr/SignedEval.java b/tajo-plan/src/main/java/org/apache/tajo/plan/expr/SignedEval.java index 9d077ba..baa78a2 100644 --- a/tajo-plan/src/main/java/org/apache/tajo/plan/expr/SignedEval.java +++ b/tajo-plan/src/main/java/org/apache/tajo/plan/expr/SignedEval.java @@ -50,6 +50,7 @@ public class SignedEval extends UnaryEval implements Cloneable { @Override @SuppressWarnings("unchecked") public Datum eval(Tuple tuple) { + super.eval(tuple); NumericDatum result = child.eval(tuple); if (negative) { return result.inverseSign(); http://git-wip-us.apache.org/repos/asf/tajo/blob/72948b63/tajo-plan/src/main/java/org/apache/tajo/plan/expr/UnaryEval.java ---------------------------------------------------------------------- diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/expr/UnaryEval.java b/tajo-plan/src/main/java/org/apache/tajo/plan/expr/UnaryEval.java index 237db00..4db2b90 100644 --- a/tajo-plan/src/main/java/org/apache/tajo/plan/expr/UnaryEval.java +++ b/tajo-plan/src/main/java/org/apache/tajo/plan/expr/UnaryEval.java @@ -67,6 +67,7 @@ public abstract class UnaryEval extends EvalNode implements Cloneable { @Override public <T extends Datum> T eval(Tuple tuple) { + super.eval(tuple); return null; } http://git-wip-us.apache.org/repos/asf/tajo/blob/72948b63/tajo-plan/src/main/java/org/apache/tajo/plan/expr/WindowFunctionEval.java ---------------------------------------------------------------------- diff --git a/tajo-plan/src/main/java/org/apache/tajo/plan/expr/WindowFunctionEval.java b/tajo-plan/src/main/java/org/apache/tajo/plan/expr/WindowFunctionEval.java index 33f9a3d..a72d826 100644 --- a/tajo-plan/src/main/java/org/apache/tajo/plan/expr/WindowFunctionEval.java +++ b/tajo-plan/src/main/java/org/apache/tajo/plan/expr/WindowFunctionEval.java @@ -65,6 +65,9 @@ public class WindowFunctionEval extends AggregationFunctionCallEval implements C @Override public Datum terminate(FunctionContext context) { + if (!isBinded) { + throw new IllegalStateException("bind() must be called before terminate()"); + } return instance.terminate(context); }
