[ASTERIXDB-2584][FUN] Support rounding digit for round()
- user model changes: yes
- user can pass optional 2nd argument to round() function
to specify the digit to round to.
- storage format changes: no
- interface changes: no
Details:
- Added new descriptor for 2-arguments version of round().
- Converted evaluator class to named class, now used by both
round() descriptors.
- Added test cases for 2-arguments version and invalid cases.
Change-Id: Ibdde2745e8bc440556e45ed07262eb33327f842b
Reviewed-on: https://asterix-gerrit.ics.uci.edu/3433
Contrib: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Hussain Towaileb <hussainht@gmail.com>
Reviewed-by: Dmitry Lychagin <dmitry.lychagin@couchbase.com>
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/round10_with_digit_double/round10_with_digit_double.1.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/round10_with_digit_double/round10_with_digit_double.1.query.sqlpp
new file mode 100644
index 0000000..6feb726
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/round10_with_digit_double/round10_with_digit_double.1.query.sqlpp
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+{
+"f1": round(456.456, 0),
+"f2": round(456.456, 2),
+"f3": round(456.456, -1),
+"f4": round(-456.456, -2),
+"f5": round(456.456, 5),
+"f6": round(-456.456, -3)
+};
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/round11_invalid/round11_invalid.1.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/round11_invalid/round11_invalid.1.query.sqlpp
new file mode 100644
index 0000000..d994728
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/round11_invalid/round11_invalid.1.query.sqlpp
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+{
+"f1": round("abc", 0) IS NULL,
+"f2": round(null, 2) IS NULL,
+"f3": round(null, missing) IS MISSING,
+"f4": round(50, "abc") IS NULL,
+"f5": round(456.456, true) IS NULL,
+"f6": round(missing, null) IS MISSING,
+"f7": round(12345, 1.2) IS NULL
+};
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/round5_with_digit_int8/round5_with_digit_int8.1.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/round5_with_digit_int8/round5_with_digit_int8.1.query.sqlpp
new file mode 100644
index 0000000..36c7e21
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/round5_with_digit_int8/round5_with_digit_int8.1.query.sqlpp
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+{
+"f1": round(int8("127"), 0),
+"f2": round(int8("127"), 1),
+"f3": round(int8("127"), -1),
+"f4": round(int8("127"), float("-1.0")),
+"f5": round(int8("127"), -1.0),
+"f6": round(int8("-127"), -2),
+"f7": round(int8("127"), -3)
+};
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/round6_with_digit_int16/round6_with_digit_int16.1.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/round6_with_digit_int16/round6_with_digit_int16.1.query.sqlpp
new file mode 100644
index 0000000..7dcf7b7
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/round6_with_digit_int16/round6_with_digit_int16.1.query.sqlpp
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+{
+"f1": round(int16("15345"), 0),
+"f2": round(int16("15345"), 1),
+"f3": round(int16("15345"), -2),
+"f4": round(int16("-15345"), -4),
+"f5": round(int16("15345"), -5)
+};
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/round7_with_digit_int32/round7_with_digit_int32.1.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/round7_with_digit_int32/round7_with_digit_int32.1.query.sqlpp
new file mode 100644
index 0000000..338f3a5
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/round7_with_digit_int32/round7_with_digit_int32.1.query.sqlpp
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+{
+"f1": round(int32("2147483647"), 0),
+"f2": round(int32("2147483647"), 1),
+"f3": round(int32("2147483647"), -1),
+"f4": round(int32("-2147483647"), -4),
+"f5": round(int32("2147483647"), -5),
+"f6": round(int32("-2147483647"), -10)
+};
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/round8_with_digit_int64/round8_with_digit_int64.1.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/round8_with_digit_int64/round8_with_digit_int64.1.query.sqlpp
new file mode 100644
index 0000000..01c128a
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/round8_with_digit_int64/round8_with_digit_int64.1.query.sqlpp
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// f4 will underflow, and will result in the lowest possible int64 value
+// f5 will overflow, and will result in the maximum possible int64 value
+
+{
+"f1": round(9223372036854775807, 0),
+"f2": round(9223372036854775807, 1),
+"f3": round(123456, -1),
+"f4": round(-9223372036854775807, -4),
+"f5": round(9223372036854775807, -5),
+"f6": round(-9223372036854775807, -11)
+};
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/round9_with_digit_float/round9_with_digit_float.1.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/round9_with_digit_float/round9_with_digit_float.1.query.sqlpp
new file mode 100644
index 0000000..58c587c
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/round9_with_digit_float/round9_with_digit_float.1.query.sqlpp
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+{
+"f1": round(float("456.456"), 0),
+"f2": round(float("456.456"), 2),
+"f3": round(float("456.456"), -1),
+"f4": round(float("-456.456"), -2),
+"f5": round(float("456.456"), 5),
+"f6": round(float("-456.456"), -3)
+};
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/round10_with_digit_double/round10_with_digit_double.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/round10_with_digit_double/round10_with_digit_double.1.adm
new file mode 100644
index 0000000..cb2517f
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/round10_with_digit_double/round10_with_digit_double.1.adm
@@ -0,0 +1 @@
+{ "f1": 456.0, "f2": 456.46, "f3": 460.0, "f4": -500.0, "f5": 456.456, "f6": 0.0 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/round11_invalid/round11_invalid.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/round11_invalid/round11_invalid.1.adm
new file mode 100644
index 0000000..3a6d78e
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/round11_invalid/round11_invalid.1.adm
@@ -0,0 +1 @@
+{ "f1": true, "f2": true, "f3": true, "f4": true, "f5": true, "f6": true, "f7": true }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/round5_with_digit_int8/round5_with_digit_int8.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/round5_with_digit_int8/round5_with_digit_int8.1.adm
new file mode 100644
index 0000000..ef36ff9
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/round5_with_digit_int8/round5_with_digit_int8.1.adm
@@ -0,0 +1 @@
+{ "f1": 127, "f2": 127, "f3": 130, "f4": 130, "f5": 130, "f6": -100, "f7": 0 }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/round6_with_digit_int16/round6_with_digit_int16.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/round6_with_digit_int16/round6_with_digit_int16.1.adm
new file mode 100644
index 0000000..059f677
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/round6_with_digit_int16/round6_with_digit_int16.1.adm
@@ -0,0 +1 @@
+{ "f1": 15345, "f2": 15345, "f3": 15300, "f4": -20000, "f5": 0 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/round7_with_digit_int32/round6_with_digit_int16.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/round7_with_digit_int32/round6_with_digit_int16.1.adm
new file mode 100644
index 0000000..c94de4d
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/round7_with_digit_int32/round6_with_digit_int16.1.adm
@@ -0,0 +1 @@
+{ "f1": 2147483647, "f2": 2147483647, "f3": 2147483650, "f4": -2147480000, "f5": 2147500000, "f6": 0 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/round8_with_digit_int64/round8_with_digit_int64.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/round8_with_digit_int64/round8_with_digit_int64.1.adm
new file mode 100644
index 0000000..af70864
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/round8_with_digit_int64/round8_with_digit_int64.1.adm
@@ -0,0 +1 @@
+{ "f1": 9223372036854775807, "f2": 9223372036854775807, "f3": 123460, "f4": -9223372036854775808, "f5": 9223372036854775807, "f6": -9223372000000000000 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/round9_with_digit_float/round9_with_digit_float.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/round9_with_digit_float/round9_with_digit_float.1.adm
new file mode 100644
index 0000000..cb2517f
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/round9_with_digit_float/round9_with_digit_float.1.adm
@@ -0,0 +1 @@
+{ "f1": 456.0, "f2": 456.46, "f3": 460.0, "f4": -500.0, "f5": 456.456, "f6": 0.0 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
index 1d924e6..9d5d44f 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
@@ -7235,6 +7235,41 @@
</compilation-unit>
</test-case>
<test-case FilePath="numeric">
+ <compilation-unit name="round5_with_digit_int8">
+ <output-dir compare="Text">round5_with_digit_int8</output-dir>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="numeric">
+ <compilation-unit name="round6_with_digit_int16">
+ <output-dir compare="Text">round6_with_digit_int16</output-dir>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="numeric">
+ <compilation-unit name="round7_with_digit_int32">
+ <output-dir compare="Text">round7_with_digit_int32</output-dir>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="numeric">
+ <compilation-unit name="round8_with_digit_int64">
+ <output-dir compare="Text">round8_with_digit_int64</output-dir>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="numeric">
+ <compilation-unit name="round9_with_digit_float">
+ <output-dir compare="Text">round9_with_digit_float</output-dir>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="numeric">
+ <compilation-unit name="round10_with_digit_double">
+ <output-dir compare="Text">round10_with_digit_double</output-dir>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="numeric">
+ <compilation-unit name="round11_invalid">
+ <output-dir compare="Text">round11_invalid</output-dir>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="numeric">
<compilation-unit name="subtract_double">
<output-dir compare="Text">subtract_double</output-dir>
</compilation-unit>
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/BuiltinFunctions.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/BuiltinFunctions.java
index 8ab1894..43664fb 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/BuiltinFunctions.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/BuiltinFunctions.java
@@ -105,6 +105,7 @@
import org.apache.asterix.om.typecomputer.impl.NumericDoubleOutputFunctionTypeComputer;
import org.apache.asterix.om.typecomputer.impl.NumericInt8OutputFunctionTypeComputer;
import org.apache.asterix.om.typecomputer.impl.NumericRound2TypeComputer;
+import org.apache.asterix.om.typecomputer.impl.NumericRoundFunctionTypeComputer;
import org.apache.asterix.om.typecomputer.impl.NumericSumAggTypeComputer;
import org.apache.asterix.om.typecomputer.impl.NumericUnaryFunctionTypeComputer;
import org.apache.asterix.om.typecomputer.impl.OpenARecordTypeComputer;
@@ -360,6 +361,8 @@
new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "floor", 1);
public static final FunctionIdentifier NUMERIC_ROUND =
new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "round", 1);
+ public static final FunctionIdentifier NUMERIC_ROUND_WITH_ROUND_DIGIT =
+ new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "round", 2);
public static final FunctionIdentifier NUMERIC_ROUND_HALF_TO_EVEN =
new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "round-half-to-even", 1);
public static final FunctionIdentifier NUMERIC_ROUND_HALF_TO_EVEN2 =
@@ -1659,7 +1662,8 @@
addFunction(NUMERIC_SIGN, NumericInt8OutputFunctionTypeComputer.INSTANCE, true);
addFunction(NUMERIC_CEILING, NumericUnaryFunctionTypeComputer.INSTANCE, true);
addFunction(NUMERIC_FLOOR, NumericUnaryFunctionTypeComputer.INSTANCE, true);
- addFunction(NUMERIC_ROUND, NumericUnaryFunctionTypeComputer.INSTANCE, true);
+ addFunction(NUMERIC_ROUND, NumericRoundFunctionTypeComputer.INSTANCE, true);
+ addFunction(NUMERIC_ROUND_WITH_ROUND_DIGIT, NumericRoundFunctionTypeComputer.INSTANCE, true);
addFunction(NUMERIC_ROUND_HALF_TO_EVEN, NumericUnaryFunctionTypeComputer.INSTANCE, true);
addFunction(NUMERIC_ROUND_HALF_TO_EVEN2, NumericRound2TypeComputer.INSTANCE, true);
addFunction(NUMERIC_TRUNC, NumericRound2TypeComputer.INSTANCE, true);
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/NumericRoundFunctionTypeComputer.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/NumericRoundFunctionTypeComputer.java
new file mode 100644
index 0000000..ffdb066
--- /dev/null
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/NumericRoundFunctionTypeComputer.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.
+ */
+/*
+ * Numeric Unary Functions like abs
+ * Author : Xiaoyu Ma@UC Irvine
+ * 01/30/2012
+ */
+package org.apache.asterix.om.typecomputer.impl;
+
+import org.apache.asterix.om.typecomputer.base.AbstractResultTypeComputer;
+import org.apache.asterix.om.types.ATypeTag;
+import org.apache.asterix.om.types.AUnionType;
+import org.apache.asterix.om.types.BuiltinType;
+import org.apache.asterix.om.types.IAType;
+import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
+import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
+
+/**
+ * Type computer for round function. This type computer receives 1 or 2 arguments. The 1st argument is the value to
+ * round, and the 2nd argument (optional) is the digit to round to. The behavior of the type computer is as follows:
+ *
+ * - For integer types, the return type is int64.
+ * - For float type, the return type is float.
+ * - For double type, the return type is double.
+ * - For any type, the return type is any.
+ * - For all other types, the return type is null.
+ */
+
+public class NumericRoundFunctionTypeComputer extends AbstractResultTypeComputer {
+ public static final NumericRoundFunctionTypeComputer INSTANCE = new NumericRoundFunctionTypeComputer();
+
+ private NumericRoundFunctionTypeComputer() {
+ }
+
+ @Override
+ protected IAType getResultType(ILogicalExpression expr, IAType... strippedInputTypes) throws AlgebricksException {
+ IAType returnType;
+ ATypeTag firstArgType = strippedInputTypes[0].getTypeTag();
+ ATypeTag secondArgType = strippedInputTypes.length > 1 ? strippedInputTypes[1].getTypeTag() : null;
+
+ switch (firstArgType) {
+ case TINYINT:
+ case SMALLINT:
+ case INTEGER:
+ case BIGINT:
+ returnType = BuiltinType.AINT64;
+ break;
+ case FLOAT:
+ case DOUBLE:
+ case ANY:
+ returnType = strippedInputTypes[0];
+ break;
+ default:
+ return BuiltinType.ANULL;
+ }
+
+ // No second argument
+ if (secondArgType == null) {
+ return returnType;
+ }
+
+ switch (secondArgType) {
+ case TINYINT:
+ case SMALLINT:
+ case INTEGER:
+ case BIGINT:
+ case ANY:
+ return returnType;
+ case FLOAT:
+ case DOUBLE:
+ return AUnionType.createNullableType(returnType);
+ default:
+ return BuiltinType.ANULL;
+ }
+ }
+}
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/NumericRoundDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/NumericRoundDescriptor.java
index 9b0dd20..5158463 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/NumericRoundDescriptor.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/NumericRoundDescriptor.java
@@ -23,49 +23,20 @@
*/
package org.apache.asterix.runtime.evaluators.functions;
-import java.io.DataOutput;
-
import org.apache.asterix.common.annotations.MissingNullInOutFunction;
-import org.apache.asterix.dataflow.data.nontagged.serde.ADoubleSerializerDeserializer;
-import org.apache.asterix.dataflow.data.nontagged.serde.AFloatSerializerDeserializer;
-import org.apache.asterix.dataflow.data.nontagged.serde.AInt16SerializerDeserializer;
-import org.apache.asterix.dataflow.data.nontagged.serde.AInt32SerializerDeserializer;
-import org.apache.asterix.dataflow.data.nontagged.serde.AInt64SerializerDeserializer;
-import org.apache.asterix.dataflow.data.nontagged.serde.AInt8SerializerDeserializer;
-import org.apache.asterix.formats.nontagged.SerializerDeserializerProvider;
-import org.apache.asterix.om.base.AMutableDouble;
-import org.apache.asterix.om.base.AMutableFloat;
-import org.apache.asterix.om.base.AMutableInt16;
-import org.apache.asterix.om.base.AMutableInt32;
-import org.apache.asterix.om.base.AMutableInt64;
-import org.apache.asterix.om.base.AMutableInt8;
import org.apache.asterix.om.functions.BuiltinFunctions;
-import org.apache.asterix.om.functions.IFunctionDescriptor;
import org.apache.asterix.om.functions.IFunctionDescriptorFactory;
-import org.apache.asterix.om.types.ATypeTag;
-import org.apache.asterix.om.types.BuiltinType;
import org.apache.asterix.runtime.evaluators.base.AbstractScalarFunctionDynamicDescriptor;
-import org.apache.asterix.runtime.exceptions.TypeMismatchException;
import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory;
import org.apache.hyracks.api.context.IHyracksTaskContext;
-import org.apache.hyracks.api.dataflow.value.ISerializerDeserializer;
import org.apache.hyracks.api.exceptions.HyracksDataException;
-import org.apache.hyracks.data.std.api.IPointable;
-import org.apache.hyracks.data.std.primitive.VoidPointable;
-import org.apache.hyracks.data.std.util.ArrayBackedValueStorage;
-import org.apache.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
@MissingNullInOutFunction
public class NumericRoundDescriptor extends AbstractScalarFunctionDynamicDescriptor {
private static final long serialVersionUID = 1L;
- public static final IFunctionDescriptorFactory FACTORY = new IFunctionDescriptorFactory() {
- @Override
- public IFunctionDescriptor createFunctionDescriptor() {
- return new NumericRoundDescriptor();
- }
- };
+ public static final IFunctionDescriptorFactory FACTORY = NumericRoundDescriptor::new;
@Override
public FunctionIdentifier getIdentifier() {
@@ -79,82 +50,7 @@
@Override
public IScalarEvaluator createScalarEvaluator(final IHyracksTaskContext ctx) throws HyracksDataException {
-
- return new IScalarEvaluator() {
-
- private ArrayBackedValueStorage resultStorage = new ArrayBackedValueStorage();
- private DataOutput out = resultStorage.getDataOutput();
- private IPointable argPtr = new VoidPointable();
- private IScalarEvaluator eval = args[0].createScalarEvaluator(ctx);
- private AMutableDouble aDouble = new AMutableDouble(0);
- private AMutableFloat aFloat = new AMutableFloat(0);
- private AMutableInt64 aInt64 = new AMutableInt64(0);
- private AMutableInt32 aInt32 = new AMutableInt32(0);
- private AMutableInt16 aInt16 = new AMutableInt16((short) 0);
- private AMutableInt8 aInt8 = new AMutableInt8((byte) 0);
- @SuppressWarnings("rawtypes")
- private ISerializerDeserializer serde;
-
- @SuppressWarnings("unchecked")
- @Override
- public void evaluate(IFrameTupleReference tuple, IPointable result) throws HyracksDataException {
- resultStorage.reset();
- eval.evaluate(tuple, argPtr);
-
- if (PointableHelper.checkAndSetMissingOrNull(result, argPtr)) {
- return;
- }
-
- byte[] data = argPtr.getByteArray();
- int offset = argPtr.getStartOffset();
-
- if (data[offset] == ATypeTag.SERIALIZED_INT8_TYPE_TAG) {
- serde = SerializerDeserializerProvider.INSTANCE
- .getSerializerDeserializer(BuiltinType.AINT8);
- byte val = AInt8SerializerDeserializer.getByte(data, offset + 1);
- aInt8.setValue(val);
- serde.serialize(aInt8, out);
- } else if (data[offset] == ATypeTag.SERIALIZED_INT16_TYPE_TAG) {
- serde = SerializerDeserializerProvider.INSTANCE
- .getSerializerDeserializer(BuiltinType.AINT16);
- short val = AInt16SerializerDeserializer.getShort(data, offset + 1);
- aInt16.setValue(val);
- serde.serialize(aInt16, out);
- } else if (data[offset] == ATypeTag.SERIALIZED_INT32_TYPE_TAG) {
- serde = SerializerDeserializerProvider.INSTANCE
- .getSerializerDeserializer(BuiltinType.AINT32);
- int val = AInt32SerializerDeserializer.getInt(data, offset + 1);
- aInt32.setValue(val);
- serde.serialize(aInt32, out);
- } else if (data[offset] == ATypeTag.SERIALIZED_INT64_TYPE_TAG) {
- serde = SerializerDeserializerProvider.INSTANCE
- .getSerializerDeserializer(BuiltinType.AINT64);
- long val = AInt64SerializerDeserializer.getLong(data, offset + 1);
- aInt64.setValue(val);
- serde.serialize(aInt64, out);
- } else if (data[offset] == ATypeTag.SERIALIZED_FLOAT_TYPE_TAG) {
- serde = SerializerDeserializerProvider.INSTANCE
- .getSerializerDeserializer(BuiltinType.AFLOAT);
- float val = AFloatSerializerDeserializer.getFloat(data, offset + 1);
- val = Math.round(val);
- aFloat.setValue(val);
- serde.serialize(aFloat, out);
- } else if (data[offset] == ATypeTag.SERIALIZED_DOUBLE_TYPE_TAG) {
- serde = SerializerDeserializerProvider.INSTANCE
- .getSerializerDeserializer(BuiltinType.ADOUBLE);
- double val = ADoubleSerializerDeserializer.getDouble(data, offset + 1);
- val = Math.round(val);
- aDouble.setValue(val);
- serde.serialize(aDouble, out);
- } else {
- throw new TypeMismatchException(sourceLoc, getIdentifier(), 0, data[offset],
- ATypeTag.SERIALIZED_INT8_TYPE_TAG, ATypeTag.SERIALIZED_INT16_TYPE_TAG,
- ATypeTag.SERIALIZED_INT32_TYPE_TAG, ATypeTag.SERIALIZED_INT64_TYPE_TAG,
- ATypeTag.SERIALIZED_FLOAT_TYPE_TAG, ATypeTag.SERIALIZED_DOUBLE_TYPE_TAG);
- }
- result.set(resultStorage);
- }
- };
+ return new NumericRoundEvaluator(ctx, args, getIdentifier(), sourceLoc);
}
};
}
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/NumericRoundEvaluator.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/NumericRoundEvaluator.java
new file mode 100644
index 0000000..c06fd35
--- /dev/null
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/NumericRoundEvaluator.java
@@ -0,0 +1,255 @@
+/*
+ * 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.asterix.runtime.evaluators.functions;
+
+import org.apache.asterix.dataflow.data.nontagged.serde.ADoubleSerializerDeserializer;
+import org.apache.asterix.dataflow.data.nontagged.serde.AFloatSerializerDeserializer;
+import org.apache.asterix.dataflow.data.nontagged.serde.AInt16SerializerDeserializer;
+import org.apache.asterix.dataflow.data.nontagged.serde.AInt32SerializerDeserializer;
+import org.apache.asterix.dataflow.data.nontagged.serde.AInt64SerializerDeserializer;
+import org.apache.asterix.dataflow.data.nontagged.serde.AInt8SerializerDeserializer;
+import org.apache.asterix.formats.nontagged.SerializerDeserializerProvider;
+import org.apache.asterix.om.base.AMutableDouble;
+import org.apache.asterix.om.base.AMutableFloat;
+import org.apache.asterix.om.base.AMutableInt64;
+import org.apache.asterix.om.types.ATypeTag;
+import org.apache.asterix.om.types.BuiltinType;
+import org.apache.asterix.om.types.EnumDeserializer;
+import org.apache.asterix.om.types.hierachy.ATypeHierarchy;
+import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory;
+import org.apache.hyracks.api.context.IHyracksTaskContext;
+import org.apache.hyracks.api.dataflow.value.ISerializerDeserializer;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.apache.hyracks.api.exceptions.SourceLocation;
+import org.apache.hyracks.data.std.api.IPointable;
+import org.apache.hyracks.data.std.primitive.VoidPointable;
+import org.apache.hyracks.data.std.util.ArrayBackedValueStorage;
+import org.apache.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
+
+/**
+ * This function rounds the numeric values. It receives 2 arguments, first is the numeric value to be rounded, second
+ * is an optional parameter to specify what digit to round to. If the provided rounding digit is positive, then the
+ * rounding should be at digits to the right of the decimal point, and if the rounding digit is negative, then the
+ * rounding should be at digits to the left of the decimal point.
+ *
+ * The return type behavior is as follows:
+ * int8, int16, int32 and int64 -> int64 is returned
+ * float -> float is returned
+ * double -> double is returned
+ * others -> null is returned
+ *
+ * Below is the formula used for rounding in the possible cases:
+ *
+ * Case 1: rounding digit is not provided or 0
+ * - Normal Math.round(123.5) -> 124
+ *
+ * Case 2: rounding digit is positive
+ * - multiplier = 10 ^ digit
+ * - Math.round(value * multiplier) / multiplier
+ * Example:
+ * - round(1.456, 2)
+ * - multiplier = 10 ^ 2 = 100
+ * - value = value * multiplier = 1.456 * 100 = 145.6
+ * - value = Math.round(value) = Math.round(145.6) = 146
+ * - value = value / multiplier = 146 / 100 = 1.46 <--- final result
+ *
+ * Case 3: rounding digit is negative
+ * - multiplier = 10 ^ Math.abs(digit)
+ * - Math.round(value / multiplier) * multiplier
+ * Example:
+ * - round(1255, -2)
+ * - multiplier = 10 ^ Math.abs(-2) = 100
+ * - value = value / multiplier = 1255 / 100 = 12.55
+ * - value = Math.round(value) = Math.around(12.55) = 13
+ * - value = value * multiplier = 13 * 100 = 1300 <--- final result
+ *
+ * Important:
+ * When dealing with big round decimal points, there is a potential of precision loss.
+ */
+
+class NumericRoundEvaluator extends AbstractScalarEval {
+
+ // Result members
+ private ArrayBackedValueStorage resultStorage = new ArrayBackedValueStorage();
+ private AMutableInt64 aInt64 = new AMutableInt64(0);
+ private AMutableFloat aFloat = new AMutableFloat(0);
+ private AMutableDouble aDouble = new AMutableDouble(0);
+
+ // Evaluators and Pointables
+ private final IScalarEvaluator valueEvaluator;
+ private IScalarEvaluator roundingDigitEvaluator;
+ private final IPointable valuePointable;
+ private IPointable roundingDigitPointable;
+
+ // Serializers/Deserializers
+ @SuppressWarnings("rawtypes")
+ protected ISerializerDeserializer int64Serde =
+ SerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.AINT64);
+ @SuppressWarnings("rawtypes")
+ protected ISerializerDeserializer floatSerde =
+ SerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.AFLOAT);
+ @SuppressWarnings("rawtypes")
+ protected ISerializerDeserializer doubleSerde =
+ SerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.ADOUBLE);
+
+ NumericRoundEvaluator(IHyracksTaskContext context, IScalarEvaluatorFactory[] argEvaluatorFactories,
+ FunctionIdentifier functionIdentifier, SourceLocation sourceLocation) throws HyracksDataException {
+ super(sourceLocation, functionIdentifier);
+
+ valueEvaluator = argEvaluatorFactories[0].createScalarEvaluator(context);
+ valuePointable = new VoidPointable();
+
+ // 2nd argument if it exists
+ if (argEvaluatorFactories.length > 1) {
+ roundingDigitEvaluator = argEvaluatorFactories[1].createScalarEvaluator(context);
+ roundingDigitPointable = new VoidPointable();
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void evaluate(IFrameTupleReference tuple, IPointable result) throws HyracksDataException {
+ resultStorage.reset();
+ valueEvaluator.evaluate(tuple, valuePointable);
+
+ if (roundingDigitEvaluator != null) {
+ roundingDigitEvaluator.evaluate(tuple, roundingDigitPointable);
+ }
+
+ if (PointableHelper.checkAndSetMissingOrNull(result, valuePointable, roundingDigitPointable)) {
+ return;
+ }
+
+ byte[] valueBytes = valuePointable.getByteArray();
+ int valueOffset = valuePointable.getStartOffset();
+ ATypeTag valueTypeTag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(valueBytes[valueOffset]);
+
+ byte[] roundingDigitBytes = null;
+ int roundingDigitOffset = 0;
+
+ if (roundingDigitEvaluator != null) {
+ roundingDigitBytes = roundingDigitPointable.getByteArray();
+ roundingDigitOffset = roundingDigitPointable.getStartOffset();
+ }
+
+ // Validity of arguments
+ if (!ATypeHierarchy.canPromote(valueTypeTag, ATypeTag.DOUBLE)) {
+ PointableHelper.setNull(result);
+ return;
+ }
+
+ // Validity of arguments
+ if (roundingDigitEvaluator != null
+ && !PointableHelper.isValidLongValue(roundingDigitBytes, roundingDigitOffset, true)) {
+ PointableHelper.setNull(result);
+ return;
+ }
+
+ // If we don't have the second argument, then rounding digit is 0, otherwise, read it from argument
+ long roundingDigit = roundingDigitEvaluator == null ? 0
+ : ATypeHierarchy.getLongValue(functionIdentifier.getName(), 2, roundingDigitBytes, roundingDigitOffset);
+
+ // Right of decimal
+ if (roundingDigit >= 0) {
+
+ // Multiplier based on round digit
+ double multiplier = Math.pow(10, Math.abs(roundingDigit));
+
+ switch (valueTypeTag) {
+ // For zero and positive digit rounding, no need to do anything for integers
+ case TINYINT:
+ aInt64.setValue(AInt8SerializerDeserializer.getByte(valueBytes, valueOffset + 1));
+ int64Serde.serialize(aInt64, resultStorage.getDataOutput());
+ break;
+ case SMALLINT:
+ aInt64.setValue(AInt16SerializerDeserializer.getShort(valueBytes, valueOffset + 1));
+ int64Serde.serialize(aInt64, resultStorage.getDataOutput());
+ break;
+ case INTEGER:
+ aInt64.setValue(AInt32SerializerDeserializer.getInt(valueBytes, valueOffset + 1));
+ int64Serde.serialize(aInt64, resultStorage.getDataOutput());
+ break;
+ case BIGINT:
+ resultStorage.set(valuePointable);
+ break;
+ case FLOAT:
+ float floatValue = AFloatSerializerDeserializer.getFloat(valueBytes, valueOffset + 1);
+ // Maintain float precision in next operation
+ aFloat.setValue(Math.round(floatValue * (float) multiplier) / (float) multiplier);
+ floatSerde.serialize(aFloat, resultStorage.getDataOutput());
+ break;
+ case DOUBLE:
+ double doubleValue = ADoubleSerializerDeserializer.getDouble(valueBytes, valueOffset + 1);
+ aDouble.setValue(Math.round(doubleValue * multiplier) / multiplier);
+ doubleSerde.serialize(aDouble, resultStorage.getDataOutput());
+ break;
+ default:
+ PointableHelper.setNull(result);
+ return;
+ }
+ }
+ // Left of decimal (negative roundingDigit value)
+ else {
+ // Multiplier based on round digit
+ double multiplier = Math.pow(10, Math.abs(roundingDigit));
+
+ switch (valueTypeTag) {
+ case TINYINT:
+ byte byteValue = AInt8SerializerDeserializer.getByte(valueBytes, valueOffset + 1);
+ aInt64.setValue((long) (Math.round(byteValue / multiplier) * multiplier));
+ int64Serde.serialize(aInt64, resultStorage.getDataOutput());
+ break;
+ case SMALLINT:
+ short shortValue = AInt16SerializerDeserializer.getShort(valueBytes, valueOffset + 1);
+ aInt64.setValue((long) (Math.round(shortValue / multiplier) * multiplier));
+ int64Serde.serialize(aInt64, resultStorage.getDataOutput());
+ break;
+ case INTEGER:
+ int intValue = AInt32SerializerDeserializer.getInt(valueBytes, valueOffset + 1);
+ aInt64.setValue((long) (Math.round(intValue / multiplier) * multiplier));
+ int64Serde.serialize(aInt64, resultStorage.getDataOutput());
+ break;
+ case BIGINT:
+ long longValue = AInt64SerializerDeserializer.getLong(valueBytes, valueOffset + 1);
+ aInt64.setValue((long) (Math.round(longValue / multiplier) * multiplier));
+ int64Serde.serialize(aInt64, resultStorage.getDataOutput());
+ break;
+ case FLOAT:
+ float floatValue = AFloatSerializerDeserializer.getFloat(valueBytes, valueOffset + 1);
+ // Maintain float precision in next operation
+ aFloat.setValue(Math.round(floatValue / (float) multiplier) * (float) multiplier);
+ floatSerde.serialize(aFloat, resultStorage.getDataOutput());
+ break;
+ case DOUBLE:
+ double doubleValue = ADoubleSerializerDeserializer.getDouble(valueBytes, valueOffset + 1);
+ aDouble.setValue(Math.round(doubleValue / multiplier) * multiplier);
+ doubleSerde.serialize(aDouble, resultStorage.getDataOutput());
+ break;
+ default:
+ PointableHelper.setNull(result);
+ return;
+ }
+ }
+
+ result.set(resultStorage);
+ }
+}
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/NumericRoundWithRoundDigitDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/NumericRoundWithRoundDigitDescriptor.java
new file mode 100644
index 0000000..a960922
--- /dev/null
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/NumericRoundWithRoundDigitDescriptor.java
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+/*
+ * Numeric function Round
+ * Author : Xiaoyu Ma@UC Irvine
+ * 01/30/2012
+ */
+package org.apache.asterix.runtime.evaluators.functions;
+
+import org.apache.asterix.common.annotations.MissingNullInOutFunction;
+import org.apache.asterix.om.functions.BuiltinFunctions;
+import org.apache.asterix.om.functions.IFunctionDescriptorFactory;
+import org.apache.asterix.runtime.evaluators.base.AbstractScalarFunctionDynamicDescriptor;
+import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory;
+import org.apache.hyracks.api.context.IHyracksTaskContext;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+
+@MissingNullInOutFunction
+public class NumericRoundWithRoundDigitDescriptor extends AbstractScalarFunctionDynamicDescriptor {
+
+ private static final long serialVersionUID = 1L;
+ public static final IFunctionDescriptorFactory FACTORY = NumericRoundWithRoundDigitDescriptor::new;
+
+ @Override
+ public FunctionIdentifier getIdentifier() {
+ return BuiltinFunctions.NUMERIC_ROUND_WITH_ROUND_DIGIT;
+ }
+
+ @Override
+ public IScalarEvaluatorFactory createEvaluatorFactory(final IScalarEvaluatorFactory[] args) {
+ return new IScalarEvaluatorFactory() {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public IScalarEvaluator createScalarEvaluator(final IHyracksTaskContext ctx) throws HyracksDataException {
+ return new NumericRoundEvaluator(ctx, args, getIdentifier(), sourceLoc);
+ }
+ };
+ }
+
+}
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/functions/FunctionCollection.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/functions/FunctionCollection.java
index acc16e1..b5b2097 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/functions/FunctionCollection.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/functions/FunctionCollection.java
@@ -377,6 +377,7 @@
import org.apache.asterix.runtime.evaluators.functions.NumericRoundDescriptor;
import org.apache.asterix.runtime.evaluators.functions.NumericRoundHalfToEven2Descriptor;
import org.apache.asterix.runtime.evaluators.functions.NumericRoundHalfToEvenDescriptor;
+import org.apache.asterix.runtime.evaluators.functions.NumericRoundWithRoundDigitDescriptor;
import org.apache.asterix.runtime.evaluators.functions.NumericSignDescriptor;
import org.apache.asterix.runtime.evaluators.functions.NumericSinDescriptor;
import org.apache.asterix.runtime.evaluators.functions.NumericSinhDescriptor;
@@ -893,6 +894,7 @@
fc.add(NumericCeilingDescriptor.FACTORY);
fc.add(NumericFloorDescriptor.FACTORY);
fc.add(NumericRoundDescriptor.FACTORY);
+ fc.add(NumericRoundWithRoundDigitDescriptor.FACTORY);
fc.add(NumericRoundHalfToEvenDescriptor.FACTORY);
fc.add(NumericRoundHalfToEven2Descriptor.FACTORY);
fc.add(NumericACosDescriptor.FACTORY);