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 2013/10/17 11:17:43 UTC
git commit: TAJO-260: Add between predicate. (hyunsik)
Updated Branches:
refs/heads/master 4074a4692 -> 95fa2667b
TAJO-260: Add between predicate. (hyunsik)
Project: http://git-wip-us.apache.org/repos/asf/incubator-tajo/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tajo/commit/95fa2667
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tajo/tree/95fa2667
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tajo/diff/95fa2667
Branch: refs/heads/master
Commit: 95fa2667b12711c7438372ae6e0bcf74f0733f14
Parents: 4074a46
Author: Hyunsik Choi <hy...@apache.org>
Authored: Thu Oct 17 18:13:31 2013 +0900
Committer: Hyunsik Choi <hy...@apache.org>
Committed: Thu Oct 17 18:13:31 2013 +0900
----------------------------------------------------------------------
CHANGES.txt | 2 +
.../apache/tajo/algebra/BetweenPredicate.java | 65 +++++
.../java/org/apache/tajo/algebra/OpType.java | 1 +
.../org/apache/tajo/engine/parser/SQLLexer.g4 | 3 +
.../org/apache/tajo/engine/parser/SQLParser.g4 | 18 +-
.../tajo/engine/eval/BetweenPredicateEval.java | 238 +++++++++++++++++++
.../org/apache/tajo/engine/eval/BinaryEval.java | 13 +-
.../org/apache/tajo/engine/eval/EvalType.java | 1 +
.../apache/tajo/engine/parser/SQLAnalyzer.java | 9 +
.../tajo/engine/planner/LogicalPlanner.java | 7 +
.../apache/tajo/engine/eval/TestPredicates.java | 59 +++++
.../tajo/engine/parser/TestSQLAnalyzer.java | 6 +-
12 files changed, 413 insertions(+), 9 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/95fa2667/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index fed5976..a487e93 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -4,6 +4,8 @@ Release 0.2.0 - unreleased
NEW FEATURES
+ TAJO-260: Add between predicate. (hyunsik)
+
TAJO-208: Implement char_length(string) function. (hyunsik)
TAJO-99: Design the interface of join enumeration algorithm. (hyunsik)
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/95fa2667/tajo-algebra/src/main/java/org/apache/tajo/algebra/BetweenPredicate.java
----------------------------------------------------------------------
diff --git a/tajo-algebra/src/main/java/org/apache/tajo/algebra/BetweenPredicate.java b/tajo-algebra/src/main/java/org/apache/tajo/algebra/BetweenPredicate.java
new file mode 100644
index 0000000..19f66af
--- /dev/null
+++ b/tajo-algebra/src/main/java/org/apache/tajo/algebra/BetweenPredicate.java
@@ -0,0 +1,65 @@
+/**
+ * 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.algebra;
+
+public class BetweenPredicate extends Expr {
+ private boolean not;
+ // if symmetric is not set, asymmetric is implicit.
+ private boolean symmetric = false;
+ private Expr predicand;
+ private Expr begin;
+ private Expr end;
+
+
+ public BetweenPredicate(boolean not, boolean symmetric, Expr predicand, Expr begin, Expr end) {
+ super(OpType.Between);
+ this.not = not;
+ this.symmetric = symmetric;
+ this.predicand = predicand;
+ this.begin = begin;
+ this.end = end;
+ }
+
+ public boolean isNot() {
+ return not;
+ }
+
+ public boolean isSymmetric() {
+ return symmetric;
+ }
+
+ public Expr predicand() {
+ return predicand;
+ }
+
+ public Expr begin() {
+ return begin;
+ }
+
+ public Expr end() {
+ return end;
+ }
+
+ @Override
+ boolean equalsTo(Expr expr) {
+ BetweenPredicate another = (BetweenPredicate) expr;
+ return symmetric == another.symmetric && predicand.equals(another.predicand) && begin.equals(another.begin) &&
+ end.equals(another.end);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/95fa2667/tajo-algebra/src/main/java/org/apache/tajo/algebra/OpType.java
----------------------------------------------------------------------
diff --git a/tajo-algebra/src/main/java/org/apache/tajo/algebra/OpType.java b/tajo-algebra/src/main/java/org/apache/tajo/algebra/OpType.java
index 799b196..3651156 100644
--- a/tajo-algebra/src/main/java/org/apache/tajo/algebra/OpType.java
+++ b/tajo-algebra/src/main/java/org/apache/tajo/algebra/OpType.java
@@ -62,6 +62,7 @@ public enum OpType {
GreaterThanOrEquals(BinaryOperator.class),
// other predicates
+ Between(BetweenPredicate.class),
CaseWhen(CaseWhenPredicate.class),
IsNullPredicate(IsNullPredicate.class),
InPredicate(InPredicate.class),
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/95fa2667/tajo-core/tajo-core-backend/src/main/antlr4/org/apache/tajo/engine/parser/SQLLexer.g4
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/antlr4/org/apache/tajo/engine/parser/SQLLexer.g4 b/tajo-core/tajo-core-backend/src/main/antlr4/org/apache/tajo/engine/parser/SQLLexer.g4
index b20544f..f0992ef 100644
--- a/tajo-core/tajo-core-backend/src/main/antlr4/org/apache/tajo/engine/parser/SQLLexer.g4
+++ b/tajo-core/tajo-core-backend/src/main/antlr4/org/apache/tajo/engine/parser/SQLLexer.g4
@@ -118,9 +118,11 @@ AS : A S;
ALL : A L L;
AND : A N D;
ANY : A N Y;
+ASYMMETRIC : A S Y M M E T R I C;
ASC : A S C;
AVG : A V G;
+BETWEEN : B E T W E E N;
BOTH : B O T H;
BY : B Y;
@@ -197,6 +199,7 @@ RIGHT : R I G H T;
RLIKE : R L I K E;
ROLLUP : R O L L U P;
+SYMMETRIC : S Y M M E T R I C;
SET : S E T;
SELECT : S E L E C T;
SOME : S O M E;
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/95fa2667/tajo-core/tajo-core-backend/src/main/antlr4/org/apache/tajo/engine/parser/SQLParser.g4
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/antlr4/org/apache/tajo/engine/parser/SQLParser.g4 b/tajo-core/tajo-core-backend/src/main/antlr4/org/apache/tajo/engine/parser/SQLParser.g4
index 1c6816a..7d48834 100644
--- a/tajo-core/tajo-core-backend/src/main/antlr4/org/apache/tajo/engine/parser/SQLParser.g4
+++ b/tajo-core/tajo-core-backend/src/main/antlr4/org/apache/tajo/engine/parser/SQLParser.g4
@@ -828,8 +828,9 @@ subquery
predicate
: comparison_predicate
+ | between_predicate
| in_predicate
- | pattern_matching_predicate
+ | pattern_matching_predicate // like predicate and other similar predicates
| null_predicate
| exists_predicate
;
@@ -856,6 +857,21 @@ comp_op
/*
===============================================================================
+ 8.3 <between predicate>
+===============================================================================
+*/
+
+between_predicate
+ : predicand=row_value_predicand between_predicate_part_2
+ ;
+
+between_predicate_part_2
+ : (NOT)? BETWEEN (ASYMMETRIC | SYMMETRIC)? begin=row_value_predicand AND end=row_value_predicand
+ ;
+
+
+/*
+===============================================================================
8.4 <in predicate>
===============================================================================
*/
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/95fa2667/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/BetweenPredicateEval.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/BetweenPredicateEval.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/BetweenPredicateEval.java
new file mode 100644
index 0000000..0215928
--- /dev/null
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/BetweenPredicateEval.java
@@ -0,0 +1,238 @@
+/**
+ * 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.eval;
+
+import com.google.gson.annotations.Expose;
+import org.apache.tajo.catalog.CatalogUtil;
+import org.apache.tajo.catalog.Schema;
+import org.apache.tajo.common.TajoDataTypes;
+import org.apache.tajo.datum.Datum;
+import org.apache.tajo.datum.DatumFactory;
+import org.apache.tajo.datum.NullDatum;
+import org.apache.tajo.storage.Tuple;
+
+public class BetweenPredicateEval extends EvalNode {
+ private static final TajoDataTypes.DataType RES_TYPE = CatalogUtil.newSimpleDataType(TajoDataTypes.Type.BOOLEAN);
+ @Expose private boolean not;
+ @Expose private boolean symmetric;
+ @Expose private EvalNode predicand;
+ @Expose private EvalNode begin;
+ @Expose private EvalNode end;
+
+ private Checker checker;
+
+ public BetweenPredicateEval(boolean not, boolean symmetric, EvalNode predicand, EvalNode begin, EvalNode end) {
+ super(EvalType.BETWEEN);
+ this.not = not;
+ this.symmetric = symmetric;
+ this.predicand = predicand;
+ this.begin = begin;
+ this.end = end;
+ }
+
+ private static interface Checker {
+ void eval(BetweenContext context, Schema schema, Tuple param);
+ }
+
+ private static class ConstantChecker implements Checker {
+ EvalNode predicand;
+ Datum begin;
+ Datum end;
+ private boolean not;
+
+ private ConstantChecker(boolean not, EvalNode predicand, Datum begin, Datum end) {
+ this.predicand = predicand;
+ this.not = not;
+ if (begin.compareTo(end) > 0) {
+ this.begin = end;
+ this.end = begin;
+ } else {
+ this.begin = begin;
+ this.end = end;
+ }
+ }
+
+ @Override
+ public void eval(BetweenContext context, Schema schema, Tuple param) {
+ predicand.eval(context.predicandContext, schema, param);
+ Datum predicandValue = predicand.terminate(context.predicandContext);
+
+ if (!(predicandValue instanceof NullDatum)) {
+ context.result =
+ DatumFactory.createBool(not ^ (predicandValue.greaterThanEqual(begin).asBool()
+ && predicandValue.lessThanEqual(end).asBool()));
+ } else {
+ context.result = NullDatum.get();
+ }
+ }
+ }
+
+ private static class AsymmetricChecker implements Checker {
+ EvalNode predicand;
+ EvalNode begin;
+ EvalNode end;
+ private boolean not;
+
+ private AsymmetricChecker(boolean not, EvalNode predicand, EvalNode begin, EvalNode end) {
+ this.not = not;
+ this.predicand = predicand;
+ this.begin = begin;
+ this.end = end;
+ }
+
+ @Override
+ public void eval(BetweenContext context, Schema schema, Tuple param) {
+ predicand.eval(context.predicandContext, schema, param);
+ Datum predicandValue = predicand.terminate(context.predicandContext);
+ begin.eval(context.beginContext, schema, param);
+ Datum beginValue = begin.terminate(context.beginContext);
+ end.eval(context.endContext, schema, param);
+ Datum endValue = begin.terminate(context.endContext);
+
+ if (!(predicandValue instanceof NullDatum || beginValue instanceof NullDatum || endValue instanceof NullDatum)) {
+ context.result =
+ DatumFactory.createBool(not ^ (predicandValue.greaterThanEqual(beginValue).asBool()
+ && predicandValue.lessThanEqual(endValue).asBool()));
+ } else {
+ context.result = NullDatum.get();
+ }
+ }
+ }
+
+ private static class SymmetricChecker implements Checker {
+ boolean not;
+ EvalNode predicand;
+ EvalNode begin;
+ EvalNode end;
+
+ SymmetricChecker(boolean not, EvalNode predicand, EvalNode begin, EvalNode end) {
+ this.not = not;
+ this.predicand = predicand;
+ this.begin = begin;
+ this.end = end;
+ }
+
+ @Override
+ public void eval(BetweenContext context, Schema schema, Tuple param) {
+ predicand.eval(context.predicandContext, schema, param);
+ Datum predicandValue = predicand.terminate(context.predicandContext);
+ begin.eval(context.beginContext, schema, param);
+ Datum beginValue = begin.terminate(context.beginContext);
+ end.eval(context.endContext, schema, param);
+ Datum endValue = begin.terminate(context.endContext);
+
+ if (!(predicandValue instanceof NullDatum || beginValue instanceof NullDatum || endValue instanceof NullDatum)) {
+ context.result = DatumFactory.createBool( not ^
+ (predicandValue.greaterThanEqual(beginValue).asBool() && predicandValue.lessThanEqual(endValue).asBool()) ||
+ (predicandValue.lessThanEqual(beginValue).asBool() && predicandValue.greaterThanEqual(endValue).asBool())
+ );
+ } else {
+ context.result = NullDatum.get();
+ }
+ }
+ }
+
+ @Override
+ public EvalContext newContext() {
+ return new BetweenContext();
+ }
+
+ @Override
+ public TajoDataTypes.DataType getValueType() {
+ return RES_TYPE;
+ }
+
+ @Override
+ public String getName() {
+ return "between";
+ }
+
+ @Override
+ public String toString() {
+ return predicand + " BETWEEN " + (symmetric ? "SYMMETRIC" : "ASYMMETRIC") + " " + begin + " AND " + end;
+ }
+
+ @Override
+ public void eval(EvalContext ctx, Schema schema, Tuple tuple) {
+ if (checker == null) {
+ if (begin.getType() == EvalType.CONST && end.getType() == EvalType.CONST) {
+ Datum beginValue = begin.terminate(null);
+ Datum endValue = end.terminate(null);
+
+ if (symmetric || beginValue.compareTo(endValue) <= 0) {
+ checker = new ConstantChecker(not, predicand, begin.terminate(null), end.terminate(null));
+ } else {
+ checker = new AsymmetricChecker(not, predicand, begin, end);
+ }
+ } else {
+ if (symmetric) {
+ checker = new SymmetricChecker(not, predicand, begin, end);
+ } else {
+ checker = new AsymmetricChecker(not, predicand, begin, end);
+ }
+ }
+ }
+
+ checker.eval((BetweenContext) ctx, schema, tuple);
+ }
+
+ @Override
+ public Datum terminate(EvalContext ctx) {
+ return ((BetweenContext)ctx).result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof BetweenPredicateEval) {
+ BetweenPredicateEval another = (BetweenPredicateEval) obj;
+ return not == another.not && symmetric == another.symmetric && predicand.equals(another.predicand) &&
+ begin.equals(another.begin) && end.equals(another.end);
+ }
+ return false;
+ }
+
+ private class BetweenContext implements EvalContext {
+ private EvalContext predicandContext;
+ private EvalContext beginContext;
+ private EvalContext endContext;
+ private Datum result;
+
+ BetweenContext() {
+ predicandContext = predicand.newContext();
+ beginContext = begin.newContext();
+ endContext = end.newContext();
+ }
+ }
+
+ @Deprecated
+ public void preOrder(EvalNodeVisitor visitor) {
+ visitor.visit(this);
+ predicand.preOrder(visitor);
+ begin.preOrder(visitor);
+ end.preOrder(visitor);
+ }
+
+ @Deprecated
+ public void postOrder(EvalNodeVisitor visitor) {
+ predicand.postOrder(visitor);
+ begin.postOrder(visitor);
+ end.postOrder(visitor);
+ visitor.visit(this);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/95fa2667/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/BinaryEval.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/BinaryEval.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/BinaryEval.java
index 90a21c5..bb25909 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/BinaryEval.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/BinaryEval.java
@@ -145,12 +145,15 @@ public class BinaryEval extends EvalNode implements Cloneable {
BinaryEvalCtx binCtx = (BinaryEvalCtx) ctx;
switch(type) {
- case AND:
- return DatumFactory.createBool(leftExpr.terminate(binCtx.left).asBool()
- && rightExpr.terminate(binCtx.right).asBool());
+ case AND: {
+ boolean left = leftExpr.terminate(binCtx.left).asBool();
+ boolean right = rightExpr.terminate(binCtx.right).asBool();
+ return DatumFactory.createBool(left && right);
+ }
case OR:
- return DatumFactory.createBool(leftExpr.terminate(binCtx.left).asBool()
- || rightExpr.terminate(binCtx.right).asBool());
+ boolean left = leftExpr.terminate(binCtx.left).asBool();
+ boolean right = rightExpr.terminate(binCtx.right).asBool();
+ return DatumFactory.createBool(left || right);
case EQUAL:
return leftExpr.terminate(binCtx.left).equalsTo(rightExpr.terminate(binCtx.right));
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/95fa2667/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalType.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalType.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalType.java
index cd80b3a..c2dc2b8 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalType.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalType.java
@@ -49,6 +49,7 @@ public enum EvalType {
CONCATENATE(BinaryEval.class, "||"),
// Other predicates
+ BETWEEN(BetweenPredicateEval.class),
CASE(CaseWhenEval.class),
IF_THEN(CaseWhenEval.IfThenEval.class),
IN(InEval.class),
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/95fa2667/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/parser/SQLAnalyzer.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/parser/SQLAnalyzer.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/parser/SQLAnalyzer.java
index 0560e8b..79e2978 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/parser/SQLAnalyzer.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/parser/SQLAnalyzer.java
@@ -411,6 +411,15 @@ public class SQLAnalyzer extends SQLParserBaseVisitor<Expr> {
}
@Override
+ public BetweenPredicate visitBetween_predicate(SQLParser.Between_predicateContext ctx) {
+ Expr predicand = visitRow_value_predicand(ctx.predicand);
+ Expr begin = visitRow_value_predicand(ctx.between_predicate_part_2().begin);
+ Expr end = visitRow_value_predicand(ctx.between_predicate_part_2().end);
+ return new BetweenPredicate(checkIfExist(ctx.between_predicate_part_2().NOT()),
+ checkIfExist(ctx.between_predicate_part_2().SYMMETRIC()), predicand, begin, end);
+ }
+
+ @Override
public CaseWhenPredicate visitSimple_case(SQLParser.Simple_caseContext ctx) {
Expr leftTerm = visitBoolean_value_expression(ctx.boolean_value_expression());
CaseWhenPredicate caseWhen = new CaseWhenPredicate();
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/95fa2667/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanner.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanner.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanner.java
index 667344e..9f7fe25 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanner.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanner.java
@@ -949,6 +949,13 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
NotExpr notExpr = (NotExpr) expr;
return new NotEval(createEvalTree(plan, block, notExpr.getChild()));
+ case Between: {
+ BetweenPredicate between = (BetweenPredicate) expr;
+ BetweenPredicateEval betweenEval = new BetweenPredicateEval(between.isNot(), between.isSymmetric(),
+ createEvalTree(plan, block, between.predicand()), createEvalTree(plan, block, between.begin()),
+ createEvalTree(plan, block, between.end()));
+ return betweenEval;
+ }
// pattern matching predicates
case LikePredicate:
case SimilarToPredicate:
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/95fa2667/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/eval/TestPredicates.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/eval/TestPredicates.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/eval/TestPredicates.java
index 6346844..d678b0b 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/eval/TestPredicates.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/eval/TestPredicates.java
@@ -47,4 +47,63 @@ public class TestPredicates extends ExprTestBase {
testEval(schema2, "table1", "_123,",
"select ltrim(col1, '_') is not null, upper(col2) is not null as a from table1", new String[]{"t", "f"});
}
+
+ @Test
+ public void testBetween() {
+ Schema schema2 = new Schema();
+ schema2.addColumn("col1", TEXT);
+ schema2.addColumn("col2", TEXT);
+ schema2.addColumn("col3", TEXT);
+
+ // constant checker
+ testEval(schema2, "table1", "b,a,c", "select col1 between 'a' and 'c' from table1", new String[]{"t"});
+ testEval(schema2, "table1", "b,a,c", "select col1 between 'c' and 'a' from table1", new String[]{"f"});
+ testEval(schema2, "table1", "b,a,c", "select col1 between symmetric 'c' and 'a' from table1", new String[]{"t"});
+ testEval(schema2, "table1", "d,a,c", "select col1 between 'a' and 'c' from table1", new String[]{"f"});
+
+ // tests for inclusive
+ testEval(schema2, "table1", "a,a,c", "select col1 between col2 and col3 from table1", new String[]{"t"});
+ testEval(schema2, "table1", "b,a,c", "select col1 between col2 and col3 from table1", new String[]{"t"});
+ testEval(schema2, "table1", "c,a,c", "select col1 between col2 and col3 from table1", new String[]{"t"});
+ testEval(schema2, "table1", "d,a,c", "select col1 between col2 and col3 from table1", new String[]{"f"});
+
+ // tests for asymmetric and symmetric
+ testEval(schema2, "table1", "b,a,c", "select col1 between col3 and col2 from table1", new String[]{"f"});
+ testEval(schema2, "table1", "b,a,c", "select col1 between symmetric col3 and col2 from table1", new String[]{"t"});
+ }
+
+ @Test
+ public void testBetween2() { // for TAJO-249
+ Schema schema3 = new Schema();
+ schema3.addColumn("date_a", INT4);
+ schema3.addColumn("date_b", INT4);
+ schema3.addColumn("date_c", INT4);
+ schema3.addColumn("date_d", INT4);
+
+ String query = "select " +
+ "case " +
+ "when date_a BETWEEN 20130705 AND 20130715 AND ((date_b BETWEEN 20100101 AND 20120601) OR date_b > 20130715) " +
+ "AND (date_c < 20120601 OR date_c > 20130715) AND date_d > 20130715" +
+ "then 1 else 0 end from table1";
+
+ testEval(schema3, "table1", "20130715,20100102,20120525,20130716", query, new String [] {"1"});
+ testEval(schema3, "table1", "20130716,20100102,20120525,20130716", query, new String [] {"0"});
+
+ // date_b
+ testEval(schema3, "table1", "20130715,20100102,20120525,20130716", query, new String [] {"1"});
+ testEval(schema3, "table1", "20130715,20120602,20120525,20130716", query, new String [] {"0"});
+ testEval(schema3, "table1", "20130715,20091201,20120525,20130716", query, new String [] {"0"});
+ testEval(schema3, "table1", "20130715,20130716,20120525,20130716", query, new String [] {"1"});
+
+ // date_c
+ testEval(schema3, "table1", "20130715,20100102,20120525,20130716", query, new String [] {"1"});
+ testEval(schema3, "table1", "20130715,20100102,20120602,20130716", query, new String [] {"0"});
+
+ testEval(schema3, "table1", "20130715,20100102,20130716,20130716", query, new String [] {"1"});
+ testEval(schema3, "table1", "20130715,20100102,20130714,20130716", query, new String [] {"0"});
+
+ // date_d
+ testEval(schema3, "table1", "20130715,20100102,20120525,20130716", query, new String [] {"1"});
+ testEval(schema3, "table1", "20130715,20100102,20120525,20130705", query, new String [] {"0"});
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/95fa2667/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/parser/TestSQLAnalyzer.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/parser/TestSQLAnalyzer.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/parser/TestSQLAnalyzer.java
index 8c3c92b..894d9ea 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/parser/TestSQLAnalyzer.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/parser/TestSQLAnalyzer.java
@@ -340,7 +340,7 @@ public class TestSQLAnalyzer {
"col is null", // 25
"col is not null", // 26
"col = null", // 27
- "col != null" // 38
+ "col != null", // 38
};
public static Expr parseExpr(String sql) {
@@ -350,8 +350,8 @@ public class TestSQLAnalyzer {
SQLParser parser = new SQLParser(tokens);
parser.setBuildParseTree(true);
SQLAnalyzer visitor = new SQLAnalyzer();
- Boolean_value_expressionContext context = parser.boolean_value_expression();
- return visitor.visitBoolean_value_expression(context);
+ SQLParser.Value_expressionContext context = parser.value_expression();
+ return visitor.visitValue_expression(context);
}
@Test