TAJO-807: Implement Round(numeric, int) function. (Seungun Choe via hyunsik)
Project: http://git-wip-us.apache.org/repos/asf/tajo/repo Commit: http://git-wip-us.apache.org/repos/asf/tajo/commit/ad53ffea Tree: http://git-wip-us.apache.org/repos/asf/tajo/tree/ad53ffea Diff: http://git-wip-us.apache.org/repos/asf/tajo/diff/ad53ffea Branch: refs/heads/window_function Commit: ad53ffeac5ee5c6b9f5b33ca45bb0c38490a8b95 Parents: f1ead5e Author: Hyunsik Choi <[email protected]> Authored: Sun May 11 04:12:13 2014 +0900 Committer: Hyunsik Choi <[email protected]> Committed: Sun May 11 04:12:13 2014 +0900 ---------------------------------------------------------------------- CHANGES | 3 + .../tajo/engine/function/math/RoundFloat8.java | 92 ++++++++++++++++++++ .../tajo/engine/function/TestMathFunctions.java | 23 +++++ 3 files changed, 118 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tajo/blob/ad53ffea/CHANGES ---------------------------------------------------------------------- diff --git a/CHANGES b/CHANGES index f5d9b72..a830776 100644 --- a/CHANGES +++ b/CHANGES @@ -12,6 +12,9 @@ Release 0.9.0 - unreleased IMPROVEMENT + TAJO-807: Implement Round(numeric, int) function. + (Seungun Choe via hyunsik) + TAJO-797: Implicit type conversion support. (hyunsik) TAJO-804: Bump up Parquet version to 1.4.2. (hyunsik) http://git-wip-us.apache.org/repos/asf/tajo/blob/ad53ffea/tajo-core/src/main/java/org/apache/tajo/engine/function/math/RoundFloat8.java ---------------------------------------------------------------------- diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/function/math/RoundFloat8.java b/tajo-core/src/main/java/org/apache/tajo/engine/function/math/RoundFloat8.java new file mode 100644 index 0000000..56d40e4 --- /dev/null +++ b/tajo-core/src/main/java/org/apache/tajo/engine/function/math/RoundFloat8.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.function.math; + +import org.apache.tajo.catalog.Column; +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.engine.eval.FunctionEval; +import org.apache.tajo.engine.function.GeneralFunction; +import org.apache.tajo.engine.function.annotation.Description; +import org.apache.tajo.engine.function.annotation.ParamTypes; +import org.apache.tajo.storage.Tuple; + +import java.text.NumberFormat; + +/** + * Function definition + * + * INT8 round(value FLOAT8) + */ +@Description( + functionName = "round", + description = "Round to s decimalN places.", + example = "> SELECT round(42.4382, 2)\n" + + "42.44", + returnType = TajoDataTypes.Type.FLOAT8, + paramTypes = {@ParamTypes(paramTypes = {TajoDataTypes.Type.FLOAT8, TajoDataTypes.Type.INT4}), + @ParamTypes(paramTypes = {TajoDataTypes.Type.INT8, TajoDataTypes.Type.INT4})} +) +public class RoundFloat8 extends GeneralFunction { + private NumberFormat numberFormat; + private boolean formatConstant; + + public RoundFloat8() { + super(new Column[] { + new Column("value", TajoDataTypes.Type.FLOAT8), + new Column("roundPoint", TajoDataTypes.Type.INT4) + }); + } + + @Override + public void init(FunctionEval.ParamType [] paramTypes) { + formatConstant = paramTypes[1] == FunctionEval.ParamType.CONSTANT; + } + + @Override + public Datum eval(Tuple params) { + Datum valueDatum = params.get(0); + Datum roundDatum = params.get(1); + + if(valueDatum instanceof NullDatum || roundDatum instanceof NullDatum) { + return NullDatum.get(); + } + + if (numberFormat == null || !formatConstant) { + numberFormat = NumberFormat.getInstance(); + numberFormat.setGroupingUsed(false); + numberFormat.setMaximumFractionDigits(roundDatum.asInt4()); + } + + double value = valueDatum.asFloat8(); + int roundPnt = roundDatum.asInt4(); + double roundNum; + + if (value > 0) { + roundNum = (long)(value * Math.pow(10, roundPnt) + 0.5d) / Math.pow(10, roundPnt); + } + else { + roundNum = (long)(value * Math.pow(10, roundPnt) - 0.5d) / Math.pow(10, roundPnt); + } + + return DatumFactory.createText(numberFormat.format(roundNum)); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/tajo/blob/ad53ffea/tajo-core/src/test/java/org/apache/tajo/engine/function/TestMathFunctions.java ---------------------------------------------------------------------- diff --git a/tajo-core/src/test/java/org/apache/tajo/engine/function/TestMathFunctions.java b/tajo-core/src/test/java/org/apache/tajo/engine/function/TestMathFunctions.java index 75dd4f7..99c31c6 100644 --- a/tajo-core/src/test/java/org/apache/tajo/engine/function/TestMathFunctions.java +++ b/tajo-core/src/test/java/org/apache/tajo/engine/function/TestMathFunctions.java @@ -425,4 +425,27 @@ public class TestMathFunctions extends ExprTestBase { public void testPi() throws IOException { testSimpleEval("select pi() as col1 ", new String[]{String.valueOf(Math.PI)}); } + + @Test + public void testRoundWithSpecifiedPrecision() throws IOException { + testSimpleEval("select round(42.4382,2) ", new String[]{"42.44"}); + testSimpleEval("select round(-42.4382,2) ", new String[]{"-42.44"}); + testSimpleEval("select round(-425,2) ", new String[]{"-425"}); + testSimpleEval("select round(425,2) ", new String[]{"425"}); + + testSimpleEval("select round(1234567890,0) ", new String[]{"1234567890"}); + testSimpleEval("select round(1234567890,1) ", new String[]{"1234567890"}); + testSimpleEval("select round(1234567890,2) ", new String[]{"1234567890"}); + + testSimpleEval("select round(1.2345678901234567,13) ", new String[]{"1.2345678901235"}); + testSimpleEval("select round(1234567890.1234567,3) ", new String[]{"1234567890.123"}); + testSimpleEval("select round(1234567890.1234567,5) ", new String[]{"1234567890.12346"}); + //testSimpleEval("select round(1234567890.1234567890,7) ", new String[]{"1234567890.1234568"}); + + Schema schema = new Schema(); + schema.addColumn("col1", FLOAT8); + schema.addColumn("col2", INT4); + + testEval(schema, "table1", ",", "select round(col1, col2) from table1", new String[]{""}); + } }
