Return-Path: X-Original-To: apmail-tajo-commits-archive@minotaur.apache.org Delivered-To: apmail-tajo-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 59C0010761 for ; Sun, 8 Dec 2013 11:23:26 +0000 (UTC) Received: (qmail 23671 invoked by uid 500); 8 Dec 2013 11:23:24 -0000 Delivered-To: apmail-tajo-commits-archive@tajo.apache.org Received: (qmail 23633 invoked by uid 500); 8 Dec 2013 11:23:22 -0000 Mailing-List: contact commits-help@tajo.incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@tajo.incubator.apache.org Delivered-To: mailing list commits@tajo.incubator.apache.org Received: (qmail 23621 invoked by uid 99); 8 Dec 2013 11:23:19 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 08 Dec 2013 11:23:19 +0000 X-ASF-Spam-Status: No, hits=-2000.1 required=5.0 tests=ALL_TRUSTED,RP_MATCHES_RCVD X-Spam-Check-By: apache.org Received: from [140.211.11.3] (HELO mail.apache.org) (140.211.11.3) by apache.org (qpsmtpd/0.29) with SMTP; Sun, 08 Dec 2013 11:23:16 +0000 Received: (qmail 23612 invoked by uid 99); 8 Dec 2013 11:22:55 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 08 Dec 2013 11:22:55 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 4F4D58AB644; Sun, 8 Dec 2013 11:22:55 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: hyunsik@apache.org To: commits@tajo.incubator.apache.org Message-Id: <2c2d0e12a762408199a2069d1c561bbb@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: git commit: TAJO-344: Tajo cannot recognize negative numeric expressions. (hyunsik) Date: Sun, 8 Dec 2013 11:22:55 +0000 (UTC) X-Virus-Checked: Checked by ClamAV on apache.org Updated Branches: refs/heads/master 8ce2a9402 -> 17d9cd735 TAJO-344: Tajo cannot recognize negative numeric expressions. (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/17d9cd73 Tree: http://git-wip-us.apache.org/repos/asf/incubator-tajo/tree/17d9cd73 Diff: http://git-wip-us.apache.org/repos/asf/incubator-tajo/diff/17d9cd73 Branch: refs/heads/master Commit: 17d9cd7357d9e4e079a61acbaa755206c5f019db Parents: 8ce2a94 Author: Hyunsik Choi Authored: Sun Dec 8 20:22:29 2013 +0900 Committer: Hyunsik Choi Committed: Sun Dec 8 20:22:29 2013 +0900 ---------------------------------------------------------------------- CHANGES.txt | 2 + .../org/apache/tajo/algebra/LiteralValue.java | 10 +- .../java/org/apache/tajo/algebra/OpType.java | 1 + .../org/apache/tajo/algebra/SignedExpr.java | 38 +++++++ .../java/org/apache/tajo/datum/Float4Datum.java | 2 +- .../java/org/apache/tajo/datum/Float8Datum.java | 4 +- .../java/org/apache/tajo/datum/Int2Datum.java | 6 +- .../java/org/apache/tajo/datum/Int4Datum.java | 2 +- .../java/org/apache/tajo/datum/Int8Datum.java | 2 +- .../org/apache/tajo/datum/NumericDatum.java | 18 ++- .../org/apache/tajo/engine/parser/SQLParser.g4 | 6 +- .../org/apache/tajo/engine/eval/EvalNode.java | 2 +- .../org/apache/tajo/engine/eval/EvalType.java | 1 + .../org/apache/tajo/engine/eval/SignedEval.java | 114 +++++++++++++++++++ .../apache/tajo/engine/function/math/Round.java | 12 +- .../tajo/engine/function/string/Substr.java | 37 +++--- .../apache/tajo/engine/parser/SQLAnalyzer.java | 14 ++- .../tajo/engine/planner/LogicalPlanner.java | 9 ++ .../tajo/engine/function/TestMathFunctions.java | 49 +++----- .../TestStringOperatorsAndFunctions.java | 40 +++---- 20 files changed, 271 insertions(+), 98 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/17d9cd73/CHANGES.txt ---------------------------------------------------------------------- diff --git a/CHANGES.txt b/CHANGES.txt index 71ba16d..0959159 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -109,6 +109,8 @@ Release 0.8.0 - unreleased BUG FIXES + TAJO-344: Tajo cannot recognize negative numeric expressions. (hyunsik) + TAJO-393: Unit tests must use test-data directory. (hyunsik) TAJO-388: limit clause does not work properly. (hyunsik) http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/17d9cd73/tajo-algebra/src/main/java/org/apache/tajo/algebra/LiteralValue.java ---------------------------------------------------------------------- diff --git a/tajo-algebra/src/main/java/org/apache/tajo/algebra/LiteralValue.java b/tajo-algebra/src/main/java/org/apache/tajo/algebra/LiteralValue.java index d713d00..4f106f2 100644 --- a/tajo-algebra/src/main/java/org/apache/tajo/algebra/LiteralValue.java +++ b/tajo-algebra/src/main/java/org/apache/tajo/algebra/LiteralValue.java @@ -19,8 +19,8 @@ package org.apache.tajo.algebra; public class LiteralValue extends Expr { - private String value; private LiteralType valueType; + private String value; public static enum LiteralType { Boolean, @@ -36,14 +36,14 @@ public class LiteralValue extends Expr { this.valueType = valueType; } - public String getValue() { - return this.value; - } - public LiteralType getValueType() { return this.valueType; } + public String getValue() { + return this.value; + } + public boolean equalsTo(Expr expr) { LiteralValue another = (LiteralValue) expr; boolean a = valueType.equals(another.valueType); http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/17d9cd73/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 3651156..3f8868b 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 @@ -84,6 +84,7 @@ public enum OpType { Modular(BinaryOperator.class), // other expressions + Sign(SignedExpr.class), Column(ColumnReferenceExpr.class), Target(Target.class), Function(FunctionExpr.class), http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/17d9cd73/tajo-algebra/src/main/java/org/apache/tajo/algebra/SignedExpr.java ---------------------------------------------------------------------- diff --git a/tajo-algebra/src/main/java/org/apache/tajo/algebra/SignedExpr.java b/tajo-algebra/src/main/java/org/apache/tajo/algebra/SignedExpr.java new file mode 100644 index 0000000..15fcb51 --- /dev/null +++ b/tajo-algebra/src/main/java/org/apache/tajo/algebra/SignedExpr.java @@ -0,0 +1,38 @@ +/** + * 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 SignedExpr extends UnaryOperator { + private boolean negative; + + public SignedExpr(boolean negative, Expr operand) { + super(OpType.Sign); + this.negative = negative; + setChild(operand); + } + + public boolean isNegative() { + return negative; + } + + @Override + boolean equalsTo(Expr expr) { + return negative == ((SignedExpr)expr).negative; + } +} http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/17d9cd73/tajo-common/src/main/java/org/apache/tajo/datum/Float4Datum.java ---------------------------------------------------------------------- diff --git a/tajo-common/src/main/java/org/apache/tajo/datum/Float4Datum.java b/tajo-common/src/main/java/org/apache/tajo/datum/Float4Datum.java index 990b6a4..87ff079 100644 --- a/tajo-common/src/main/java/org/apache/tajo/datum/Float4Datum.java +++ b/tajo-common/src/main/java/org/apache/tajo/datum/Float4Datum.java @@ -26,7 +26,7 @@ import org.apache.tajo.util.NumberUtil; import java.nio.ByteBuffer; -public class Float4Datum extends Datum implements NumericDatum { +public class Float4Datum extends NumericDatum { private static final int size = 4; @Expose float val; http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/17d9cd73/tajo-common/src/main/java/org/apache/tajo/datum/Float8Datum.java ---------------------------------------------------------------------- diff --git a/tajo-common/src/main/java/org/apache/tajo/datum/Float8Datum.java b/tajo-common/src/main/java/org/apache/tajo/datum/Float8Datum.java index bb49e28..c6535c2 100644 --- a/tajo-common/src/main/java/org/apache/tajo/datum/Float8Datum.java +++ b/tajo-common/src/main/java/org/apache/tajo/datum/Float8Datum.java @@ -32,12 +32,10 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -public class Float8Datum extends Datum implements NumericDatum { +public class Float8Datum extends NumericDatum { private static final int size = 8; @Expose private double val; - private static final Log LOG = LogFactory.getLog(Float8Datum.class); - public Float8Datum() { super(TajoDataTypes.Type.FLOAT8); } http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/17d9cd73/tajo-common/src/main/java/org/apache/tajo/datum/Int2Datum.java ---------------------------------------------------------------------- diff --git a/tajo-common/src/main/java/org/apache/tajo/datum/Int2Datum.java b/tajo-common/src/main/java/org/apache/tajo/datum/Int2Datum.java index bee8c47..1cb9d1d 100644 --- a/tajo-common/src/main/java/org/apache/tajo/datum/Int2Datum.java +++ b/tajo-common/src/main/java/org/apache/tajo/datum/Int2Datum.java @@ -19,8 +19,6 @@ package org.apache.tajo.datum; import com.google.gson.annotations.Expose; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.apache.tajo.common.TajoDataTypes; import org.apache.tajo.datum.exception.InvalidOperationException; import org.apache.tajo.util.NumberUtil; @@ -28,12 +26,10 @@ import org.apache.tajo.util.NumberUtil; import java.nio.ByteBuffer; -public class Int2Datum extends Datum implements NumericDatum { +public class Int2Datum extends NumericDatum { private static final int size = 2; @Expose private short val; - private static final Log LOG = LogFactory.getLog(Int2Datum.class); - public Int2Datum() { super(TajoDataTypes.Type.INT2); } http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/17d9cd73/tajo-common/src/main/java/org/apache/tajo/datum/Int4Datum.java ---------------------------------------------------------------------- diff --git a/tajo-common/src/main/java/org/apache/tajo/datum/Int4Datum.java b/tajo-common/src/main/java/org/apache/tajo/datum/Int4Datum.java index ee66700..fa7f6c5 100644 --- a/tajo-common/src/main/java/org/apache/tajo/datum/Int4Datum.java +++ b/tajo-common/src/main/java/org/apache/tajo/datum/Int4Datum.java @@ -26,7 +26,7 @@ import org.apache.tajo.util.NumberUtil; import java.nio.ByteBuffer; -public class Int4Datum extends Datum implements NumericDatum { +public class Int4Datum extends NumericDatum { private static final int size = 4; @Expose private int val; http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/17d9cd73/tajo-common/src/main/java/org/apache/tajo/datum/Int8Datum.java ---------------------------------------------------------------------- diff --git a/tajo-common/src/main/java/org/apache/tajo/datum/Int8Datum.java b/tajo-common/src/main/java/org/apache/tajo/datum/Int8Datum.java index a1664c5..ffe9654 100644 --- a/tajo-common/src/main/java/org/apache/tajo/datum/Int8Datum.java +++ b/tajo-common/src/main/java/org/apache/tajo/datum/Int8Datum.java @@ -27,7 +27,7 @@ import org.apache.tajo.util.NumberUtil; import java.nio.ByteBuffer; -public class Int8Datum extends Datum implements NumericDatum { +public class Int8Datum extends NumericDatum { private static final int size = 8; @Expose private long val; http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/17d9cd73/tajo-common/src/main/java/org/apache/tajo/datum/NumericDatum.java ---------------------------------------------------------------------- diff --git a/tajo-common/src/main/java/org/apache/tajo/datum/NumericDatum.java b/tajo-common/src/main/java/org/apache/tajo/datum/NumericDatum.java index 745b720..b12ae91 100644 --- a/tajo-common/src/main/java/org/apache/tajo/datum/NumericDatum.java +++ b/tajo-common/src/main/java/org/apache/tajo/datum/NumericDatum.java @@ -19,15 +19,21 @@ package org.apache.tajo.datum; -public interface NumericDatum { +import org.apache.tajo.common.TajoDataTypes; - Datum plus(Datum datum); +public abstract class NumericDatum extends Datum { + + public NumericDatum(TajoDataTypes.Type type) { + super(type); + } + + public abstract Datum plus(Datum datum); - Datum minus(Datum datum); + public abstract Datum minus(Datum datum); - Datum multiply(Datum datum); + public abstract Datum multiply(Datum datum); - Datum divide(Datum datum); + public abstract Datum divide(Datum datum); - void inverseSign(); + public abstract void inverseSign(); } http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/17d9cd73/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 b2c9717..c806846 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 @@ -441,7 +441,11 @@ numeric_value_expression ; term - : left=numeric_primary ((MULTIPLY|DIVIDE|MODULAR) right=numeric_primary)* + : left=factor ((MULTIPLY|DIVIDE|MODULAR) right=factor)* + ; + +factor + : (sign)? numeric_primary ; array http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/17d9cd73/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalNode.java ---------------------------------------------------------------------- diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalNode.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalNode.java index 45f3736..2e797fb 100644 --- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalNode.java +++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/EvalNode.java @@ -88,7 +88,7 @@ public abstract class EvalNode implements Cloneable, GsonObject { public void eval(EvalContext ctx, Schema schema, Tuple tuple) {} - public abstract Datum terminate(EvalContext ctx); + public abstract T terminate(EvalContext ctx); @Deprecated public void preOrder(EvalNodeVisitor visitor) { http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/17d9cd73/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 c2dc2b8..71db934 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 @@ -55,6 +55,7 @@ public enum EvalType { IN(InEval.class), // Value or Reference + SIGNED(SignedEval.class), CAST(CastEval.class), ROW_CONSTANT(RowConstantEval.class), FIELD(FieldEval.class), http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/17d9cd73/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/SignedEval.java ---------------------------------------------------------------------- diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/SignedEval.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/SignedEval.java new file mode 100644 index 0000000..b0ba813 --- /dev/null +++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/eval/SignedEval.java @@ -0,0 +1,114 @@ +/** + * 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.Schema; +import org.apache.tajo.common.TajoDataTypes.DataType; +import org.apache.tajo.datum.NumericDatum; +import org.apache.tajo.storage.Tuple; + +public class SignedEval extends EvalNode implements Cloneable { + @Expose private EvalNode childEval; + @Expose private boolean negative; + + public SignedEval(boolean negative, EvalNode childEval) { + super(EvalType.SIGNED); + this.negative = negative; + this.childEval = childEval; + } + + @Override + public EvalContext newContext() { + SignedEvalCtx newCtx = new SignedEvalCtx(); + newCtx.childExprCtx = childEval.newContext(); + return newCtx; + } + + public boolean isNegative() { + return negative; + } + + public EvalNode getChild() { + return childEval; + } + + @Override + public DataType getValueType() { + return childEval.getValueType(); + } + + @Override + public String getName() { + return "?"; + } + + @Override + public void eval(EvalContext ctx, Schema schema, Tuple tuple) { + childEval.eval(((SignedEvalCtx) ctx).childExprCtx, schema, tuple); + } + + @Override + public NumericDatum terminate(EvalContext ctx) { + NumericDatum result = childEval.terminate(((SignedEvalCtx) ctx).childExprCtx); + if (negative) { + result.inverseSign(); + } + return result; + } + + @Override + public String toString() { + return (negative ? "-" : "+") + childEval.toString(); + } + + @Override + public void preOrder(EvalNodeVisitor visitor) { + visitor.visit(this); + childEval.preOrder(visitor); + } + + @Override + public void postOrder(EvalNodeVisitor visitor) { + childEval.postOrder(visitor); + visitor.visit(this); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof SignedEval) { + SignedEval other = (SignedEval) obj; + return negative == other.negative && this.childEval.equals(other.childEval); + } else { + return false; + } + } + + @Override + public Object clone() throws CloneNotSupportedException { + SignedEval eval = (SignedEval) super.clone(); + eval.negative = negative; + eval.childEval = (EvalNode) this.childEval.clone(); + return eval; + } + + private class SignedEvalCtx implements EvalContext { + EvalContext childExprCtx; + } +} http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/17d9cd73/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/function/math/Round.java ---------------------------------------------------------------------- diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/function/math/Round.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/function/math/Round.java index f95e330..e033df0 100644 --- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/function/math/Round.java +++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/function/math/Round.java @@ -45,6 +45,16 @@ public class Round extends GeneralFunction { return NullDatum.get(); } - return DatumFactory.createInt8(Math.round(valueDatum.asFloat8())); + double value = valueDatum.asFloat8(); + + // Note: there are various round up/down approaches (https://en.wikipedia.org/wiki/Rounding#Tie-breaking). + // Math.round uses an approach different from other programming languages, so the results of round function + // can be different from other DBMSs. For example, Math.round(-5.5) returns -5. In contrast, + // round function in MySQL and PostgreSQL returns -6. The below code is a workaround code for this. + if (value < 0) { + return DatumFactory.createInt8((long) Math.ceil(value - 0.5d)); + } else { + return DatumFactory.createInt8((long) Math.floor(value + 0.5d)); + } } } http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/17d9cd73/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/function/string/Substr.java ---------------------------------------------------------------------- diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/function/string/Substr.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/function/string/Substr.java index cb42e3c..9652cdc 100644 --- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/function/string/Substr.java +++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/function/string/Substr.java @@ -36,40 +36,45 @@ public class Substr extends GeneralFunction { super(new Column[] { new Column("text", TajoDataTypes.Type.TEXT), new Column("from", TajoDataTypes.Type.INT4), - new Column("length", TajoDataTypes.Type.INT4) //optional + new Column("count", TajoDataTypes.Type.INT4) //optional }); } @Override public Datum eval(Tuple params) { Datum valueDatum = params.get(0); - if(valueDatum instanceof NullDatum) { + Datum fromDatum = params.get(1); + Datum countDatum = params.size() > 2 ? params.get(2) : null; + + if(valueDatum instanceof NullDatum || fromDatum instanceof NullDatum || countDatum instanceof NullDatum) { return NullDatum.get(); } - Datum fromDatum = params.get(1); - Datum lengthDatum = params.size() > 2 ? params.get(2) : null; String value = valueDatum.asChars(); - int valueLength = value.length(); + int from = fromDatum.asInt4(); + int strLength = value.length(); + int count; - int from = fromDatum.asInt4() - 1; - if (from >= valueLength) { - return DatumFactory.createText(""); + if (countDatum == null) { + count = strLength; + } else { + count = (countDatum.asInt4() + from) - 1; } - int length = (lengthDatum == null) ? valueLength : lengthDatum.asInt4(); + if (count > strLength) { + count = strLength; + } - if (from < 0) { + if (from < 1) { from = 0; - length = (lengthDatum == null) ? value.length() : length - 1; + } else { + from --; } - int to = from + length; - - if (to > valueLength) { - to = valueLength; + if (from >= count) { + return DatumFactory.createText(""); } - return DatumFactory.createText(value.substring(from, to)); + return DatumFactory.createText(value.substring(from, count)); } } http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/17d9cd73/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 737f774..d8f259e 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 @@ -592,14 +592,14 @@ public class SQLAnalyzer extends SQLParserBaseVisitor { @Override public Expr visitTerm(SQLParser.TermContext ctx) { - Expr current = visitNumeric_primary(ctx.numeric_primary(0)); + Expr current = visitFactor(ctx.factor(0)); Expr left; Expr right; for (int i = 1; i < ctx.getChildCount(); i++) { left = current; TerminalNode operator = (TerminalNode) ctx.getChild(i++); - right = visitNumeric_primary((Numeric_primaryContext) ctx.getChild(i)); + right = visitFactor((FactorContext) ctx.getChild(i)); if (operator.getSymbol().getType() == MULTIPLY) { current = new BinaryOperator(OpType.Multiply, left, right); @@ -613,6 +613,14 @@ public class SQLAnalyzer extends SQLParserBaseVisitor { return current; } + @Override public Expr visitFactor(SQLParser.FactorContext ctx) { + Expr current = visitNumeric_primary(ctx.numeric_primary()); + if (checkIfExist(ctx.sign()) && checkIfExist(ctx.sign().MINUS())) { + current = new SignedExpr(true, current); + } + return current; + } + @Override public Expr visitNumeric_primary(SQLParser.Numeric_primaryContext ctx) { if (ctx.value_expression_primary() != null) { @@ -761,7 +769,7 @@ public class SQLAnalyzer extends SQLParserBaseVisitor { @Override public FunctionExpr visitGeneral_set_function(SQLParser.General_set_functionContext ctx) { String signature = ctx.set_function_type().getText(); - boolean distinct = checkIfExist(ctx.set_qualifier()) && checkIfExist(ctx.set_qualifier().DISTINCT()) ? true : false; + boolean distinct = checkIfExist(ctx.set_qualifier()) && checkIfExist(ctx.set_qualifier().DISTINCT()); Expr param = visitValue_expression(ctx.value_expression()); return new GeneralSetFunctionExpr(signature, distinct, param); http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/17d9cd73/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 76b9239..5e48f4a 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 @@ -1065,6 +1065,15 @@ public class LogicalPlanner extends BaseAlgebraVisitor