[ASTERIXDB-2689][FUN] Make numeric functions return NULL on invalid arguments p2

- user model changes: no
- storage format changes: no
- interface changes: no

Details:
Make numeric functions return NULL on invalid arguments.
round(num), round(num, num), trunc(num, num), round-half-to-even(num, num).

- added warning to round() function
- extracted evaluators of trunc() and round-half-to-even() to a common evaluator
- renamed checkWarnOrSetInteger() to setInteger()

Change-Id: I1ccef0740d64cce3ada8b60d3a699748e7ef8776
Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/4704
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: Ali Alsuliman <ali.al.solaiman@gmail.com>
Reviewed-by: Dmitry Lychagin <dmitry.lychagin@couchbase.com>
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fun_return_null/numeric_fun/numeric_fun_002/numeric_fun_002.01.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fun_return_null/numeric_fun/numeric_fun_002/numeric_fun_002.01.ddl.sqlpp
new file mode 100644
index 0000000..dd607f7
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fun_return_null/numeric_fun/numeric_fun_002/numeric_fun_002.01.ddl.sqlpp
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+use test;
+
+create type t1 as {
+id:   int,
+str1: string
+};
+
+create dataset ds1(t1) primary key id;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fun_return_null/numeric_fun/numeric_fun_002/numeric_fun_002.02.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fun_return_null/numeric_fun/numeric_fun_002/numeric_fun_002.02.update.sqlpp
new file mode 100644
index 0000000..05c78d2
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fun_return_null/numeric_fun/numeric_fun_002/numeric_fun_002.02.update.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+use test;
+
+insert into ds1([
+{"id": 1, "str1": "text", "str2": "text"}
+]);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fun_return_null/numeric_fun/numeric_fun_002/numeric_fun_002.03.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fun_return_null/numeric_fun/numeric_fun_002/numeric_fun_002.03.query.sqlpp
new file mode 100644
index 0000000..c3bba54
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fun_return_null/numeric_fun/numeric_fun_002/numeric_fun_002.03.query.sqlpp
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+/*
+ *  Description: tests reporting invalid argument type for numeric functions
+ */
+// requesttype=application/json
+// param max-warnings:json=1000
+
+use test;
+
+set `import-private-functions` "true";
+
+from ds1 as ds1
+select
+round(str1) as f1, round(str2) as f2, round("text") as f3,
+round(id, str1) as f4, round(id, str2) as f5, round(id, "text") as f6,
+trunc(str1, id) as f7, trunc(str2, id) as f8, trunc("text", id) as f9,
+trunc(id, str1) as f10, trunc(id, str2) as f11, trunc(id, "text") as f12,
+`round-half-to-even`(str1, id) as f13, `round-half-to-even`(str2, id) as f14, `round-half-to-even`("text", id) as f15,
+`round-half-to-even`(id, str1) as f16, `round-half-to-even`(id, str2) as f17, `round-half-to-even`(id, "text") as f18;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fun_return_null/numeric_fun/numeric_fun_002/numeric_fun_002.04.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fun_return_null/numeric_fun/numeric_fun_002/numeric_fun_002.04.ddl.sqlpp
new file mode 100644
index 0000000..548e632
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fun_return_null/numeric_fun/numeric_fun_002/numeric_fun_002.04.ddl.sqlpp
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+drop dataverse test if exists;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/fun_return_null/numeric_fun/numeric_fun_002/numeric_fun_002.03.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/fun_return_null/numeric_fun/numeric_fun_002/numeric_fun_002.03.adm
new file mode 100644
index 0000000..91137d9
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/fun_return_null/numeric_fun/numeric_fun_002/numeric_fun_002.03.adm
@@ -0,0 +1 @@
+{ "f1": null, "f3": null, "f4": null, "f5": null, "f6": null, "f7": null, "f9": null, "f10": null, "f11": null, "f12": null, "f13": null, "f15": null, "f16": null, "f17": null, "f18": null, "f2": null, "f8": null, "f14": null }
\ 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 e81c6a3..c4c5e8f 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
@@ -13819,5 +13819,31 @@
         <source-location>false</source-location>
       </compilation-unit>
     </test-case>
+    <test-case FilePath="fun_return_null/numeric_fun" check-warnings="true">
+      <compilation-unit name="numeric_fun_002">
+        <output-dir compare="Text">numeric_fun_002</output-dir>
+        <expected-warn>Type mismatch: function round expects its 1st input parameter to be of type tinyint, smallint, integer, bigint, float or double, but the actual input type is string</expected-warn>
+        <expected-warn>Type mismatch: function round-half-to-even expects its 2nd input parameter to be of type tinyint, smallint, integer, bigint, float or double, but the actual input type is string</expected-warn>
+        <expected-warn>Type mismatch: function trunc expects its 2nd input parameter to be of type tinyint, smallint, integer, bigint, float or double, but the actual input type is string</expected-warn>
+        <expected-warn>Type mismatch: function round-half-to-even expects its 1st input parameter to be of type tinyint, smallint, integer, bigint, float or double, but the actual input type is string</expected-warn>
+        <expected-warn>Type mismatch: function trunc expects its 1st input parameter to be of type tinyint, smallint, integer, bigint, float or double, but the actual input type is string</expected-warn>
+        <expected-warn>Type mismatch: function round expects its 2nd input parameter to be of type tinyint, smallint, integer or bigint, but the actual input type is string</expected-warn>
+
+        <expected-warn>Type mismatch: function round expects its 1st input parameter to be of type tinyint, smallint, integer, bigint, float or double, but the actual input type is string</expected-warn>
+        <expected-warn>Type mismatch: function round-half-to-even expects its 2nd input parameter to be of type tinyint, smallint, integer, bigint, float or double, but the actual input type is string</expected-warn>
+        <expected-warn>Type mismatch: function trunc expects its 2nd input parameter to be of type tinyint, smallint, integer, bigint, float or double, but the actual input type is string</expected-warn>
+        <expected-warn>Type mismatch: function round expects its 1st input parameter to be of type tinyint, smallint, integer, bigint, float or double, but the actual input type is string</expected-warn>
+        <expected-warn>Type mismatch: function round-half-to-even expects its 2nd input parameter to be of type tinyint, smallint, integer, bigint, float or double, but the actual input type is string</expected-warn>
+        <expected-warn>Type mismatch: function trunc expects its 2nd input parameter to be of type tinyint, smallint, integer, bigint, float or double, but the actual input type is string</expected-warn>
+
+        <expected-warn>Type mismatch: function round expects its 1st input parameter to be of type tinyint, smallint, integer, bigint, float or double, but the actual input type is string</expected-warn>
+        <expected-warn>Type mismatch: function round-half-to-even expects its 2nd input parameter to be of type tinyint, smallint, integer, bigint, float or double, but the actual input type is string</expected-warn>
+        <expected-warn>Type mismatch: function trunc expects its 2nd input parameter to be of type tinyint, smallint, integer, bigint, float or double, but the actual input type is string</expected-warn>
+        <expected-warn>Type mismatch: function round expects its 1st input parameter to be of type tinyint, smallint, integer, bigint, float or double, but the actual input type is string</expected-warn>
+        <expected-warn>Type mismatch: function round-half-to-even expects its 2nd input parameter to be of type tinyint, smallint, integer, bigint, float or double, but the actual input type is string</expected-warn>
+        <expected-warn>Type mismatch: function trunc expects its 2nd input parameter to be of type tinyint, smallint, integer, bigint, float or double, but the actual input type is string</expected-warn>
+        <source-location>false</source-location>
+      </compilation-unit>
+    </test-case>
   </test-group>
 </test-suite>
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 8bd6454..64d44bd 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
@@ -106,8 +106,7 @@
 import org.apache.asterix.om.typecomputer.impl.NumericAddSubMulDivTypeComputer;
 import org.apache.asterix.om.typecomputer.impl.NumericBinaryToDoubleTypeComputer;
 import org.apache.asterix.om.typecomputer.impl.NumericDivideTypeComputer;
-import org.apache.asterix.om.typecomputer.impl.NumericRound2TypeComputer;
-import org.apache.asterix.om.typecomputer.impl.NumericRoundFunctionTypeComputer;
+import org.apache.asterix.om.typecomputer.impl.NumericRoundTypeComputer;
 import org.apache.asterix.om.typecomputer.impl.NumericSumAggTypeComputer;
 import org.apache.asterix.om.typecomputer.impl.NumericUnaryTypeComputer;
 import org.apache.asterix.om.typecomputer.impl.OpenARecordTypeComputer;
@@ -1681,11 +1680,11 @@
         addFunction(NUMERIC_SIGN, NumericUnaryTypeComputer.INSTANCE_INT8, true);
         addFunction(NUMERIC_CEILING, NumericUnaryTypeComputer.INSTANCE, true);
         addFunction(NUMERIC_FLOOR, NumericUnaryTypeComputer.INSTANCE, true);
-        addFunction(NUMERIC_ROUND, NumericRoundFunctionTypeComputer.INSTANCE, true);
-        addFunction(NUMERIC_ROUND_WITH_ROUND_DIGIT, NumericRoundFunctionTypeComputer.INSTANCE, true);
+        addFunction(NUMERIC_ROUND, NumericRoundTypeComputer.INSTANCE, true);
+        addFunction(NUMERIC_ROUND_WITH_ROUND_DIGIT, NumericRoundTypeComputer.INSTANCE, true);
         addFunction(NUMERIC_ROUND_HALF_TO_EVEN, NumericUnaryTypeComputer.INSTANCE, true);
-        addFunction(NUMERIC_ROUND_HALF_TO_EVEN2, NumericRound2TypeComputer.INSTANCE, true);
-        addFunction(NUMERIC_TRUNC, NumericRound2TypeComputer.INSTANCE, true);
+        addFunction(NUMERIC_ROUND_HALF_TO_EVEN2, NumericRoundTypeComputer.INSTANCE_ROUND_HF_TRUNC, true);
+        addFunction(NUMERIC_TRUNC, NumericRoundTypeComputer.INSTANCE_ROUND_HF_TRUNC, true);
 
         addFunction(BINARY_LENGTH, UnaryBinaryInt64TypeComputer.INSTANCE, true);
         addFunction(PARSE_BINARY, ABinaryTypeComputer.INSTANCE, true);
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/NumericRound2TypeComputer.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/NumericRound2TypeComputer.java
deleted file mode 100644
index 09bcfd9..0000000
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/NumericRound2TypeComputer.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * 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 round half to even
- * Author : Xiaoyu Ma@UC Irvine
- * 01/30/2012
- */
-package org.apache.asterix.om.typecomputer.impl;
-
-import org.apache.asterix.om.exceptions.TypeMismatchException;
-import org.apache.asterix.om.typecomputer.base.AbstractResultTypeComputer;
-import org.apache.asterix.om.types.ATypeTag;
-import org.apache.asterix.om.types.IAType;
-import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
-import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
-import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
-import org.apache.hyracks.api.exceptions.SourceLocation;
-
-public class NumericRound2TypeComputer extends AbstractResultTypeComputer {
-
-    public static final NumericRound2TypeComputer INSTANCE = new NumericRound2TypeComputer();
-
-    private NumericRound2TypeComputer() {
-
-    }
-
-    @Override
-    protected void checkArgType(FunctionIdentifier funcId, int argIndex, IAType type, SourceLocation sourceLoc)
-            throws AlgebricksException {
-        ATypeTag tag = type.getTypeTag();
-        if (argIndex == 0) {
-            switch (tag) {
-                case TINYINT:
-                case SMALLINT:
-                case INTEGER:
-                case BIGINT:
-                case FLOAT:
-                case DOUBLE:
-                    break;
-                default:
-                    throw new TypeMismatchException(sourceLoc, funcId, argIndex, tag, ATypeTag.TINYINT,
-                            ATypeTag.SMALLINT, ATypeTag.INTEGER, ATypeTag.BIGINT, ATypeTag.FLOAT, ATypeTag.DOUBLE);
-            }
-        }
-        if (argIndex == 1) {
-            switch (tag) {
-                case TINYINT:
-                case SMALLINT:
-                case INTEGER:
-                case BIGINT:
-                    break;
-                default:
-                    throw new TypeMismatchException(sourceLoc, funcId, argIndex, tag, ATypeTag.TINYINT,
-                            ATypeTag.SMALLINT, ATypeTag.INTEGER, ATypeTag.BIGINT);
-            }
-        }
-    }
-
-    @Override
-    protected IAType getResultType(ILogicalExpression expr, IAType... strippedInputTypes) throws AlgebricksException {
-        ATypeTag tag = strippedInputTypes[0].getTypeTag();
-        switch (tag) {
-            case TINYINT:
-            case SMALLINT:
-            case INTEGER:
-            case BIGINT:
-            case FLOAT:
-            case DOUBLE:
-            case ANY:
-                return strippedInputTypes[0];
-            default:
-                return null;
-        }
-    }
-}
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/NumericRoundTypeComputer.java
similarity index 77%
rename from asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/NumericRoundFunctionTypeComputer.java
rename to asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/NumericRoundTypeComputer.java
index ffdb066..5c6a15b 100644
--- 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/NumericRoundTypeComputer.java
@@ -32,20 +32,25 @@
 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:
+ * Type computer for round functions. 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
+ * depending on the instance:
  *
- * - For integer types, the return type is int64.
+ * - For integer types, the return type is int64 or the same integer type.
  * - 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();
+public class NumericRoundTypeComputer extends AbstractResultTypeComputer {
+    public static final NumericRoundTypeComputer INSTANCE = new NumericRoundTypeComputer(false);
+    public static final NumericRoundTypeComputer INSTANCE_ROUND_HF_TRUNC = new NumericRoundTypeComputer(true);
 
-    private NumericRoundFunctionTypeComputer() {
+    private final boolean returnSameIntType;
+
+    private NumericRoundTypeComputer(boolean returnSameIntType) {
+        this.returnSameIntType = returnSameIntType;
     }
 
     @Override
@@ -59,7 +64,7 @@
             case SMALLINT:
             case INTEGER:
             case BIGINT:
-                returnType = BuiltinType.AINT64;
+                returnType = returnSameIntType ? strippedInputTypes[0] : BuiltinType.AINT64;
                 break;
             case FLOAT:
             case DOUBLE:
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/common/ArgumentUtils.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/common/ArgumentUtils.java
index 7c27e0e..da81f27 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/common/ArgumentUtils.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/common/ArgumentUtils.java
@@ -38,9 +38,9 @@
  */
 public final class ArgumentUtils {
 
-    public static final byte[] EXPECTED_NUMERIC = { 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 };
+    public static final byte[] NUMERIC_TYPES = { 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 };
     private static final DoubleToInt32TypeConvertComputer LAX_DOUBLE_TO_INT32 =
             DoubleToInt32TypeConvertComputer.getInstance(false);
 
@@ -56,12 +56,11 @@
      * @param value data to be checked
      * @param outInteger where the integer read from {@code value} will be stored
      */
-    public static boolean checkWarnOrSetInteger(IEvaluatorContext ctx, SourceLocation sourceLoc,
-            FunctionIdentifier funcID, int argIdx, byte[] value, int offset, AMutableInt32 outInteger)
-            throws HyracksDataException {
+    public static boolean setInteger(IEvaluatorContext ctx, SourceLocation sourceLoc, FunctionIdentifier funcID,
+            int argIdx, byte[] value, int offset, AMutableInt32 outInteger) throws HyracksDataException {
         byte type = value[offset];
         if (ATypeHierarchy.getTypeDomain(VALUE_TYPE_MAPPING[type]) != ATypeHierarchy.Domain.NUMERIC) {
-            ExceptionUtil.warnTypeMismatch(ctx, sourceLoc, funcID, type, argIdx, EXPECTED_NUMERIC);
+            ExceptionUtil.warnTypeMismatch(ctx, sourceLoc, funcID, type, argIdx, NUMERIC_TYPES);
             return false;
         }
         // deal with NaN, +/-INF
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/AbstractConcatStringEval.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/AbstractConcatStringEval.java
index a61d96e..f008432 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/AbstractConcatStringEval.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/AbstractConcatStringEval.java
@@ -183,8 +183,7 @@
         if (isReturnNull) {
             PointableHelper.setNull(result);
             if (unsupportedType != null && unsupportedType != ATypeTag.NULL) {
-                ExceptionUtil.warnTypeMismatch(ctx, sourceLoc, functionIdentifier, unsupportedType.serialize(),
-                        argIndex, expectedType);
+                ExceptionUtil.warnTypeMismatch(ctx, srcLoc, funID, unsupportedType.serialize(), argIndex, expectedType);
             }
             return;
         }
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/AbstractScalarEval.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/AbstractScalarEval.java
index 6cb3666..20f5f03 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/AbstractScalarEval.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/AbstractScalarEval.java
@@ -24,11 +24,11 @@
 import org.apache.hyracks.api.exceptions.SourceLocation;
 
 public abstract class AbstractScalarEval implements IScalarEvaluator {
-    protected final SourceLocation sourceLoc;
-    protected final FunctionIdentifier functionIdentifier;
+    protected final SourceLocation srcLoc;
+    protected final FunctionIdentifier funID;
 
     public AbstractScalarEval(SourceLocation sourceLoc, FunctionIdentifier functionIdentifier) {
-        this.sourceLoc = sourceLoc;
-        this.functionIdentifier = functionIdentifier;
+        this.srcLoc = sourceLoc;
+        this.funID = functionIdentifier;
     }
 }
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/AbstractStringStringStringIntEval.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/AbstractStringStringStringIntEval.java
index 4aae469..d878eee 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/AbstractStringStringStringIntEval.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/AbstractStringStringStringIntEval.java
@@ -110,7 +110,7 @@
             return;
         }
         // check that the int argument is numeric without fractions (in case arg is double or float)
-        if (!ArgumentUtils.checkWarnOrSetInteger(ctx, sourceLoc, funcID, 3, bytes3, start3, mutableInt)) {
+        if (!ArgumentUtils.setInteger(ctx, sourceLoc, funcID, 3, bytes3, start3, mutableInt)) {
             PointableHelper.setNull(result);
             return;
         }
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/AbstractUnaryNumericFunctionEval.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/AbstractUnaryNumericFunctionEval.java
index 6c199d0..18a853e 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/AbstractUnaryNumericFunctionEval.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/AbstractUnaryNumericFunctionEval.java
@@ -137,7 +137,7 @@
             double val = ADoubleSerializerDeserializer.getDouble(data, offset + 1);
             processDouble(val, result);
         } else {
-            ExceptionUtil.warnTypeMismatch(ctx, sourceLoc, funcID, data[offset], 0, ArgumentUtils.EXPECTED_NUMERIC);
+            ExceptionUtil.warnTypeMismatch(ctx, sourceLoc, funcID, data[offset], 0, ArgumentUtils.NUMERIC_TYPES);
             PointableHelper.setNull(result);
         }
     }
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayExceptDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayExceptDescriptor.java
index d4e3fac..d3a7e64 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayExceptDescriptor.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayExceptDescriptor.java
@@ -157,15 +157,13 @@
             ATypeTag arg2TypeTag = ATYPETAGDESERIALIZER.deserialize(arg2Bytes[arg2StartOffset]);
 
             if (!arg1TypeTag.isListType()) {
-                ExceptionUtil.warnTypeMismatch(ctx, sourceLoc, functionIdentifier, arg1Bytes[arg1StartOffset], 0,
-                        ATypeTag.ARRAY);
+                ExceptionUtil.warnTypeMismatch(ctx, srcLoc, funID, arg1Bytes[arg1StartOffset], 0, ATypeTag.ARRAY);
                 PointableHelper.setNull(result);
                 return;
             }
 
             if (!arg2TypeTag.isListType()) {
-                ExceptionUtil.warnTypeMismatch(ctx, sourceLoc, functionIdentifier, arg2Bytes[arg2StartOffset], 1,
-                        ATypeTag.ARRAY);
+                ExceptionUtil.warnTypeMismatch(ctx, srcLoc, funID, arg2Bytes[arg2StartOffset], 1, ATypeTag.ARRAY);
                 PointableHelper.setNull(result);
                 return;
             }
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayRangeEvaluator.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayRangeEvaluator.java
index 8c81c38..3c98fd3 100755
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayRangeEvaluator.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayRangeEvaluator.java
@@ -98,7 +98,7 @@
             return;
         }
 
-        String n = functionIdentifier.getName();
+        String n = funID.getName();
         ATypeTag startTag = ATYPETAGDESERIALIZER.deserialize(start.getTag());
         ATypeTag endTag = ATYPETAGDESERIALIZER.deserialize(end.getTag());
         ATypeTag stepTag = ATypeTag.INTEGER;
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayReplaceEvaluator.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayReplaceEvaluator.java
index 63e3192..329fa78 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayReplaceEvaluator.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayReplaceEvaluator.java
@@ -136,7 +136,7 @@
         }
 
         double maxDouble = -1;
-        String name = functionIdentifier.getName();
+        String name = funID.getName();
         if (maxEval != null) {
             maxEval.evaluate(tuple, maxArg);
             ATypeTag maxTag = ATYPETAGDESERIALIZER.deserialize(maxArg.getTag());
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArraySliceEvaluator.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArraySliceEvaluator.java
index 6b0b844..e2c6f84 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArraySliceEvaluator.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArraySliceEvaluator.java
@@ -268,12 +268,12 @@
                 value = ADoubleSerializerDeserializer.getDouble(data, offset);
                 break;
             default:
-                throw new UnsupportedItemTypeException(sourceLoc, functionIdentifier, typeTag.serialize());
+                throw new UnsupportedItemTypeException(srcLoc, funID, typeTag.serialize());
         }
 
         // Values like 1, 2, 3.0 are ok, but 0.3 and 3.5 are not accepted, also handle NaN and INF/-INF
         if (Double.isNaN(value) || Double.isInfinite(value) || value > Math.floor(value)) {
-            throw new InvalidDataFormatException(sourceLoc, functionIdentifier, typeTag.serialize());
+            throw new InvalidDataFormatException(srcLoc, funID, typeTag.serialize());
         }
 
         return (int) value;
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/DecodeDataverseNameDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/DecodeDataverseNameDescriptor.java
index 3274926..1ec6a5a 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/DecodeDataverseNameDescriptor.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/DecodeDataverseNameDescriptor.java
@@ -93,7 +93,7 @@
                         // Type check.
                         if (bytes[offset] != ATypeTag.SERIALIZED_STRING_TYPE_TAG) {
                             PointableHelper.setNull(result);
-                            ExceptionUtil.warnTypeMismatch(ctx, sourceLoc, getIdentifier(), bytes[offset], 0,
+                            ExceptionUtil.warnTypeMismatch(ctx, srcLoc, getIdentifier(), bytes[offset], 0,
                                     ATypeTag.STRING);
                             return;
                         }
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/NumericATan2Descriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/NumericATan2Descriptor.java
index da52b4a..815b479 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/NumericATan2Descriptor.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/NumericATan2Descriptor.java
@@ -19,7 +19,7 @@
 package org.apache.asterix.runtime.evaluators.functions;
 
 import static org.apache.asterix.om.types.ATypeTag.VALUE_TYPE_MAPPING;
-import static org.apache.asterix.runtime.evaluators.common.ArgumentUtils.EXPECTED_NUMERIC;
+import static org.apache.asterix.runtime.evaluators.common.ArgumentUtils.NUMERIC_TYPES;
 
 import java.io.DataOutput;
 
@@ -115,7 +115,7 @@
                         byte type = data[offset];
                         if (ATypeHierarchy.getTypeDomain(VALUE_TYPE_MAPPING[type]) != ATypeHierarchy.Domain.NUMERIC) {
                             ExceptionUtil.warnTypeMismatch(ctx, sourceLoc, getIdentifier(), type, argIdx,
-                                    EXPECTED_NUMERIC);
+                                    NUMERIC_TYPES);
                             return true;
                         }
                         return false;
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
index f04e4cd..8367d2b 100644
--- 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
@@ -19,6 +19,11 @@
 
 package org.apache.asterix.runtime.evaluators.functions;
 
+import static org.apache.asterix.om.types.ATypeTag.SERIALIZED_INT16_TYPE_TAG;
+import static org.apache.asterix.om.types.ATypeTag.SERIALIZED_INT32_TYPE_TAG;
+import static org.apache.asterix.om.types.ATypeTag.SERIALIZED_INT64_TYPE_TAG;
+import static org.apache.asterix.om.types.ATypeTag.SERIALIZED_INT8_TYPE_TAG;
+
 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;
@@ -29,10 +34,12 @@
 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.exceptions.ExceptionUtil;
 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.asterix.runtime.evaluators.common.ArgumentUtils;
 import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
 import org.apache.hyracks.algebricks.runtime.base.IEvaluatorContext;
 import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
@@ -88,6 +95,7 @@
 
 class NumericRoundEvaluator extends AbstractScalarEval {
 
+    private final IEvaluatorContext ctx;
     // Result members
     private ArrayBackedValueStorage resultStorage = new ArrayBackedValueStorage();
     private AMutableInt64 aInt64 = new AMutableInt64(0);
@@ -111,10 +119,14 @@
     protected ISerializerDeserializer doubleSerde =
             SerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.ADOUBLE);
 
+    private static final byte[] INT_TYPES = new byte[] { SERIALIZED_INT8_TYPE_TAG, SERIALIZED_INT16_TYPE_TAG,
+            SERIALIZED_INT32_TYPE_TAG, SERIALIZED_INT64_TYPE_TAG };
+
     NumericRoundEvaluator(IEvaluatorContext context, IScalarEvaluatorFactory[] argEvaluatorFactories,
             FunctionIdentifier functionIdentifier, SourceLocation sourceLocation) throws HyracksDataException {
         super(sourceLocation, functionIdentifier);
 
+        ctx = context;
         valueEvaluator = argEvaluatorFactories[0].createScalarEvaluator(context);
         valuePointable = new VoidPointable();
 
@@ -153,6 +165,7 @@
 
         // Validity of arguments
         if (!ATypeHierarchy.canPromote(valueTypeTag, ATypeTag.DOUBLE)) {
+            ExceptionUtil.warnTypeMismatch(ctx, srcLoc, funID, valueBytes[valueOffset], 0, ArgumentUtils.NUMERIC_TYPES);
             PointableHelper.setNull(result);
             return;
         }
@@ -160,13 +173,14 @@
         // Validity of arguments
         if (roundingDigitEvaluator != null
                 && !PointableHelper.isValidLongValue(roundingDigitBytes, roundingDigitOffset, true)) {
+            ExceptionUtil.warnTypeMismatch(ctx, srcLoc, funID, roundingDigitBytes[roundingDigitOffset], 1, INT_TYPES);
             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);
+                : ATypeHierarchy.getLongValue(funID.getName(), 2, roundingDigitBytes, roundingDigitOffset);
 
         // Right of decimal
         if (roundingDigit >= 0) {
@@ -203,6 +217,7 @@
                     doubleSerde.serialize(aDouble, resultStorage.getDataOutput());
                     break;
                 default:
+                    ExceptionUtil.warnUnsupportedType(ctx, srcLoc, funID.getName(), valueTypeTag);
                     PointableHelper.setNull(result);
                     return;
             }
@@ -245,6 +260,7 @@
                     doubleSerde.serialize(aDouble, resultStorage.getDataOutput());
                     break;
                 default:
+                    ExceptionUtil.warnUnsupportedType(ctx, srcLoc, funID.getName(), valueTypeTag);
                     PointableHelper.setNull(result);
                     return;
             }
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/NumericRoundHalfToEven2Descriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/NumericRoundHalfToEven2Descriptor.java
index 988c08d..df2cde0 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/NumericRoundHalfToEven2Descriptor.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/NumericRoundHalfToEven2Descriptor.java
@@ -23,51 +23,23 @@
  */
 package org.apache.asterix.runtime.evaluators.functions;
 
-import java.io.DataOutput;
 import java.math.BigDecimal;
 
 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.IEvaluatorContext;
 import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
 import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory;
-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 NumericRoundHalfToEven2Descriptor extends AbstractScalarFunctionDynamicDescriptor {
 
     private static final long serialVersionUID = 1L;
-    public static final IFunctionDescriptorFactory FACTORY = new IFunctionDescriptorFactory() {
-        @Override
-        public IFunctionDescriptor createFunctionDescriptor() {
-            return new NumericRoundHalfToEven2Descriptor();
-        }
-    };
+    public static final IFunctionDescriptorFactory FACTORY = NumericRoundHalfToEven2Descriptor::new;
 
     @Override
     public FunctionIdentifier getIdentifier() {
@@ -81,118 +53,9 @@
 
             @Override
             public IScalarEvaluator createScalarEvaluator(final IEvaluatorContext ctx) throws HyracksDataException {
-
-                return new IScalarEvaluator() {
-
-                    private ArrayBackedValueStorage resultStorage = new ArrayBackedValueStorage();
-                    private DataOutput out = resultStorage.getDataOutput();
-                    private IPointable argValue = new VoidPointable();
-                    private IPointable argPrecision = new VoidPointable();
-                    private IScalarEvaluator eval = args[0].createScalarEvaluator(ctx);
-                    private IScalarEvaluator precision = args[1].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;
-
-                    private int getPrecision() throws HyracksDataException {
-                        byte[] bytes = argPrecision.getByteArray();
-                        int offset = argPrecision.getStartOffset();
-
-                        if (bytes[offset] == ATypeTag.SERIALIZED_INT8_TYPE_TAG) {
-                            return AInt8SerializerDeserializer.getByte(bytes, offset + 1);
-                        } else if (bytes[offset] == ATypeTag.SERIALIZED_INT16_TYPE_TAG) {
-                            return AInt16SerializerDeserializer.getShort(bytes, offset + 1);
-                        } else if (bytes[offset] == ATypeTag.SERIALIZED_INT32_TYPE_TAG) {
-                            return AInt32SerializerDeserializer.getInt(bytes, offset + 1);
-                        } else if (bytes[offset] == ATypeTag.SERIALIZED_INT64_TYPE_TAG) {
-                            return (int) AInt64SerializerDeserializer.getLong(bytes, offset + 1);
-                        } else {
-                            throw new TypeMismatchException(sourceLoc, getIdentifier(), 1, bytes[offset],
-                                    ATypeTag.SERIALIZED_INT8_TYPE_TAG, ATypeTag.SERIALIZED_INT16_TYPE_TAG,
-                                    ATypeTag.SERIALIZED_INT32_TYPE_TAG, ATypeTag.SERIALIZED_INT64_TYPE_TAG);
-                        }
-                    }
-
-                    @SuppressWarnings("unchecked")
-                    @Override
-                    public void evaluate(IFrameTupleReference tuple, IPointable result) throws HyracksDataException {
-                        resultStorage.reset();
-                        eval.evaluate(tuple, argValue);
-                        precision.evaluate(tuple, argPrecision);
-
-                        if (PointableHelper.checkAndSetMissingOrNull(result, argValue, argPrecision)) {
-                            return;
-                        }
-
-                        byte[] data = argValue.getByteArray();
-                        int offset = argValue.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);
-                            if (Float.isNaN(val) || Float.isInfinite(val) || Float.compare(val, -0.0F) == 0
-                                    || Float.compare(val, 0.0F) == 0) {
-                                aFloat.setValue(val);
-                                serde.serialize(aFloat, out);
-                            } else {
-                                BigDecimal r = new BigDecimal(Float.toString(val));
-                                aFloat.setValue(r.setScale(getPrecision(), BigDecimal.ROUND_HALF_EVEN).floatValue());
-                                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);
-                            if (Double.isNaN(val) || Double.isInfinite(val) || Double.compare(val, -0.0D) == 0
-                                    || Double.compare(val, 0.0D) == 0) {
-                                aDouble.setValue(val);
-                                serde.serialize(aDouble, out);
-                            } else {
-                                BigDecimal r = new BigDecimal(Double.toString(val));
-                                aDouble.setValue(r.setScale(getPrecision(), BigDecimal.ROUND_HALF_EVEN).doubleValue());
-                                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 NumericRoundTruncEvaluator(ctx, args, BigDecimal.ROUND_HALF_EVEN, getIdentifier(),
+                        sourceLoc);
             }
         };
     }
-
 }
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/NumericRoundTruncEvaluator.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/NumericRoundTruncEvaluator.java
new file mode 100644
index 0000000..a59e330
--- /dev/null
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/NumericRoundTruncEvaluator.java
@@ -0,0 +1,140 @@
+/*
+ * 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 static org.apache.asterix.om.types.ATypeTag.VALUE_TYPE_MAPPING;
+
+import java.io.DataOutput;
+import java.math.BigDecimal;
+
+import org.apache.asterix.dataflow.data.nontagged.serde.ADoubleSerializerDeserializer;
+import org.apache.asterix.dataflow.data.nontagged.serde.AFloatSerializerDeserializer;
+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.AMutableInt32;
+import org.apache.asterix.om.exceptions.ExceptionUtil;
+import org.apache.asterix.om.types.ATypeTag;
+import org.apache.asterix.om.types.BuiltinType;
+import org.apache.asterix.om.types.hierachy.ATypeHierarchy;
+import org.apache.asterix.runtime.evaluators.common.ArgumentUtils;
+import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+import org.apache.hyracks.algebricks.runtime.base.IEvaluatorContext;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory;
+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;
+
+/**
+ * Used by {@link NumericTruncDescriptor trunc()} and {@link NumericRoundHalfToEven2Descriptor round-half-to-even()}.
+ */
+class NumericRoundTruncEvaluator extends AbstractScalarEval {
+
+    private final ArrayBackedValueStorage resultStorage = new ArrayBackedValueStorage();
+    private final DataOutput out = resultStorage.getDataOutput();
+    private final IPointable valueArg = new VoidPointable();
+    private final IPointable precisionArg = new VoidPointable();
+    private final AMutableDouble aDouble = new AMutableDouble(0);
+    private final AMutableFloat aFloat = new AMutableFloat(0);
+    private final AMutableInt32 aInt32 = new AMutableInt32(0);
+    private final IEvaluatorContext ctx;
+    private final IScalarEvaluator valueEval;
+    private final IScalarEvaluator precisionEval;
+    private final int roundingMode;
+
+    NumericRoundTruncEvaluator(IEvaluatorContext ctx, IScalarEvaluatorFactory[] args, int roundingMode,
+            FunctionIdentifier funID, SourceLocation srcLoc) throws HyracksDataException {
+        super(srcLoc, funID);
+        this.ctx = ctx;
+        this.valueEval = args[0].createScalarEvaluator(ctx);
+        this.precisionEval = args[1].createScalarEvaluator(ctx);
+        this.roundingMode = roundingMode;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public void evaluate(IFrameTupleReference tuple, IPointable result) throws HyracksDataException {
+        resultStorage.reset();
+        valueEval.evaluate(tuple, valueArg);
+        precisionEval.evaluate(tuple, precisionArg);
+
+        if (PointableHelper.checkAndSetMissingOrNull(result, valueArg, precisionArg)) {
+            return;
+        }
+
+        byte[] value = valueArg.getByteArray();
+        int offset = valueArg.getStartOffset();
+        byte valueTag = value[offset];
+        if (ATypeHierarchy.getTypeDomain(VALUE_TYPE_MAPPING[valueTag]) != ATypeHierarchy.Domain.NUMERIC) {
+            ExceptionUtil.warnTypeMismatch(ctx, srcLoc, funID, valueTag, 0, ArgumentUtils.NUMERIC_TYPES);
+            PointableHelper.setNull(result);
+            return;
+        }
+        if (!ArgumentUtils.setInteger(ctx, srcLoc, funID, 1, precisionArg.getByteArray(), precisionArg.getStartOffset(),
+                aInt32)) {
+            PointableHelper.setNull(result);
+            return;
+        }
+
+        if (valueTag == ATypeTag.SERIALIZED_INT8_TYPE_TAG || valueTag == ATypeTag.SERIALIZED_INT16_TYPE_TAG
+                || valueTag == ATypeTag.SERIALIZED_INT32_TYPE_TAG || valueTag == ATypeTag.SERIALIZED_INT64_TYPE_TAG) {
+            result.set(valueArg);
+            return;
+        }
+
+        @SuppressWarnings("rawtypes")
+        ISerializerDeserializer serde;
+        if (valueTag == ATypeTag.SERIALIZED_FLOAT_TYPE_TAG) {
+            serde = SerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.AFLOAT);
+            float val = AFloatSerializerDeserializer.getFloat(value, offset + 1);
+            if (Float.isNaN(val) || Float.isInfinite(val) || Float.compare(val, -0.0F) == 0
+                    || Float.compare(val, 0.0F) == 0) {
+                aFloat.setValue(val);
+                serde.serialize(aFloat, out);
+            } else {
+                BigDecimal r = new BigDecimal(Float.toString(val));
+                aFloat.setValue(r.setScale(aInt32.getIntegerValue(), roundingMode).floatValue());
+                serde.serialize(aFloat, out);
+            }
+        } else if (valueTag == ATypeTag.SERIALIZED_DOUBLE_TYPE_TAG) {
+            serde = SerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.ADOUBLE);
+            double val = ADoubleSerializerDeserializer.getDouble(value, offset + 1);
+            if (Double.isNaN(val) || Double.isInfinite(val) || Double.compare(val, -0.0D) == 0
+                    || Double.compare(val, 0.0D) == 0) {
+                aDouble.setValue(val);
+                serde.serialize(aDouble, out);
+            } else {
+                BigDecimal r = new BigDecimal(Double.toString(val));
+                aDouble.setValue(r.setScale(aInt32.getIntegerValue(), roundingMode).doubleValue());
+                serde.serialize(aDouble, out);
+            }
+        } else {
+            ExceptionUtil.warnUnsupportedType(ctx, srcLoc, funID.getName(), VALUE_TYPE_MAPPING[valueTag]);
+            PointableHelper.setNull(result);
+            return;
+        }
+        result.set(resultStorage);
+    }
+}
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/NumericTruncDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/NumericTruncDescriptor.java
index 1cd1b49..2b5dee8 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/NumericTruncDescriptor.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/NumericTruncDescriptor.java
@@ -23,51 +23,23 @@
  */
 package org.apache.asterix.runtime.evaluators.functions;
 
-import java.io.DataOutput;
 import java.math.BigDecimal;
 
 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.IEvaluatorContext;
 import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
 import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory;
-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 NumericTruncDescriptor extends AbstractScalarFunctionDynamicDescriptor {
 
     private static final long serialVersionUID = 1L;
-    public static final IFunctionDescriptorFactory FACTORY = new IFunctionDescriptorFactory() {
-        @Override
-        public IFunctionDescriptor createFunctionDescriptor() {
-            return new NumericTruncDescriptor();
-        }
-    };
+    public static final IFunctionDescriptorFactory FACTORY = NumericTruncDescriptor::new;
 
     @Override
     public FunctionIdentifier getIdentifier() {
@@ -81,117 +53,8 @@
 
             @Override
             public IScalarEvaluator createScalarEvaluator(IEvaluatorContext ctx) throws HyracksDataException {
-                return new NumericTruncEvaluator(args, ctx);
+                return new NumericRoundTruncEvaluator(ctx, args, BigDecimal.ROUND_DOWN, getIdentifier(), sourceLoc);
             }
         };
     }
-
-    class NumericTruncEvaluator implements IScalarEvaluator {
-        private final ArrayBackedValueStorage resultStorage = new ArrayBackedValueStorage();
-        private final DataOutput out = resultStorage.getDataOutput();
-        private final IPointable argValue = new VoidPointable();
-        private final IPointable argPrecision = new VoidPointable();
-        private final IScalarEvaluator eval;
-        private final IScalarEvaluator precision;
-        private final AMutableDouble aDouble = new AMutableDouble(0);
-        private final AMutableFloat aFloat = new AMutableFloat(0);
-        private final AMutableInt64 aInt64 = new AMutableInt64(0);
-        private final AMutableInt32 aInt32 = new AMutableInt32(0);
-        private final AMutableInt16 aInt16 = new AMutableInt16((short) 0);
-        private final AMutableInt8 aInt8 = new AMutableInt8((byte) 0);
-        @SuppressWarnings("rawtypes")
-        private ISerializerDeserializer serde;
-
-        NumericTruncEvaluator(IScalarEvaluatorFactory[] args, IEvaluatorContext ctx) throws HyracksDataException {
-            eval = args[0].createScalarEvaluator(ctx);
-            precision = args[1].createScalarEvaluator(ctx);
-        }
-
-        private int getPrecision() throws HyracksDataException {
-            byte[] bytes = argPrecision.getByteArray();
-            int offset = argPrecision.getStartOffset();
-
-            if (bytes[offset] == ATypeTag.SERIALIZED_INT8_TYPE_TAG) {
-                return AInt8SerializerDeserializer.getByte(bytes, offset + 1);
-            } else if (bytes[offset] == ATypeTag.SERIALIZED_INT16_TYPE_TAG) {
-                return AInt16SerializerDeserializer.getShort(bytes, offset + 1);
-            } else if (bytes[offset] == ATypeTag.SERIALIZED_INT32_TYPE_TAG) {
-                return AInt32SerializerDeserializer.getInt(bytes, offset + 1);
-            } else if (bytes[offset] == ATypeTag.SERIALIZED_INT64_TYPE_TAG) {
-                return (int) AInt64SerializerDeserializer.getLong(bytes, offset + 1);
-            } else {
-                throw new TypeMismatchException(sourceLoc, getIdentifier(), 1, bytes[offset],
-                        ATypeTag.SERIALIZED_INT8_TYPE_TAG, ATypeTag.SERIALIZED_INT16_TYPE_TAG,
-                        ATypeTag.SERIALIZED_INT32_TYPE_TAG, ATypeTag.SERIALIZED_INT64_TYPE_TAG);
-            }
-        }
-
-        @SuppressWarnings("unchecked")
-        @Override
-        public void evaluate(IFrameTupleReference tuple, IPointable result) throws HyracksDataException {
-            resultStorage.reset();
-            eval.evaluate(tuple, argValue);
-            precision.evaluate(tuple, argPrecision);
-
-            if (PointableHelper.checkAndSetMissingOrNull(result, argValue, argPrecision)) {
-                return;
-            }
-
-            byte[] data = argValue.getByteArray();
-            int offset = argValue.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);
-                if (Float.isNaN(val) || Float.isInfinite(val) || Float.compare(val, -0.0F) == 0
-                        || Float.compare(val, 0.0F) == 0) {
-                    aFloat.setValue(val);
-                    serde.serialize(aFloat, out);
-                } else {
-                    BigDecimal r = new BigDecimal(Float.toString(val));
-                    aFloat.setValue(r.setScale(getPrecision(), BigDecimal.ROUND_DOWN).floatValue());
-                    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);
-                if (Double.isNaN(val) || Double.isInfinite(val) || Double.compare(val, -0.0D) == 0
-                        || Double.compare(val, 0.0D) == 0) {
-                    aDouble.setValue(val);
-                    serde.serialize(aDouble, out);
-                } else {
-                    BigDecimal r = new BigDecimal(Double.toString(val));
-                    aDouble.setValue(r.setScale(getPrecision(), BigDecimal.ROUND_DOWN).doubleValue());
-                    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);
-        }
-    }
-
 }
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/RandomWithSeedDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/RandomWithSeedDescriptor.java
index 7f24e8d..2836eae 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/RandomWithSeedDescriptor.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/RandomWithSeedDescriptor.java
@@ -19,7 +19,7 @@
 
 package org.apache.asterix.runtime.evaluators.functions;
 
-import static org.apache.asterix.runtime.evaluators.common.ArgumentUtils.EXPECTED_NUMERIC;
+import static org.apache.asterix.runtime.evaluators.common.ArgumentUtils.NUMERIC_TYPES;
 
 import org.apache.asterix.common.annotations.MissingNullInOutFunction;
 import org.apache.asterix.om.exceptions.ExceptionUtil;
@@ -86,7 +86,7 @@
                                 break;
                             default:
                                 ExceptionUtil.warnTypeMismatch(ctx, sourceLoc, getIdentifier(), bytes[offset], 0,
-                                        EXPECTED_NUMERIC);
+                                        NUMERIC_TYPES);
                                 PointableHelper.setNull(resultPointable);
                                 break;
                         }
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/StringRegExpReplaceWithFlagDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/StringRegExpReplaceWithFlagDescriptor.java
index f43fedc..2ebed70 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/StringRegExpReplaceWithFlagDescriptor.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/StringRegExpReplaceWithFlagDescriptor.java
@@ -18,6 +18,8 @@
  */
 package org.apache.asterix.runtime.evaluators.functions;
 
+import static org.apache.asterix.runtime.evaluators.common.ArgumentUtils.NUMERIC_TYPES;
+
 import java.io.IOException;
 import java.util.Arrays;
 
@@ -80,8 +82,8 @@
                                 case BIGINT:
                                 case FLOAT:
                                 case DOUBLE:
-                                    if (!ArgumentUtils.checkWarnOrSetInteger(ctx, sourceLoc, funcID, argIdx, bytes,
-                                            start, mutableInt)) {
+                                    if (!ArgumentUtils.setInteger(ctx, sourceLoc, funcID, argIdx, bytes, start,
+                                            mutableInt)) {
                                         return false;
                                     }
                                     limit = mutableInt.getIntegerValue();
@@ -104,8 +106,7 @@
 
                     private byte[] getExpectedTypes() {
                         if (expectedTypes == null) {
-                            expectedTypes = Arrays.copyOf(ArgumentUtils.EXPECTED_NUMERIC,
-                                    ArgumentUtils.EXPECTED_NUMERIC.length + 1);
+                            expectedTypes = Arrays.copyOf(NUMERIC_TYPES, NUMERIC_TYPES.length + 1);
                             expectedTypes[expectedTypes.length - 1] = ATypeTag.SERIALIZED_STRING_TYPE_TAG;
                         }
                         return expectedTypes;
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/StringRepeatDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/StringRepeatDescriptor.java
index 83e3f8e..7fe0148 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/StringRepeatDescriptor.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/StringRepeatDescriptor.java
@@ -83,8 +83,7 @@
                         // Gets the repeating times.
                         byte[] bytes = argNumber.getByteArray();
                         int offset = argNumber.getStartOffset();
-                        if (!ArgumentUtils.checkWarnOrSetInteger(ctx, sourceLoc, getIdentifier(), 1, bytes, offset,
-                                mutableInt)) {
+                        if (!ArgumentUtils.setInteger(ctx, sourceLoc, getIdentifier(), 1, bytes, offset, mutableInt)) {
                             PointableHelper.setNull(result);
                             return;
                         }
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/Substring2Eval.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/Substring2Eval.java
index 55cacb9..124ae40 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/Substring2Eval.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/Substring2Eval.java
@@ -80,8 +80,7 @@
         byte[] bytes = argStart.getByteArray();
         int offset = argStart.getStartOffset();
         // check that the int argument is numeric without fractions (in case arg is double or float)
-        if (!ArgumentUtils.checkWarnOrSetInteger(context, sourceLoc, functionIdentifier, 1, bytes, offset,
-                mutableInt)) {
+        if (!ArgumentUtils.setInteger(context, srcLoc, funID, 1, bytes, offset, mutableInt)) {
             PointableHelper.setNull(result);
             return;
         }
@@ -91,7 +90,7 @@
         int len = argString.getLength();
         if (bytes[offset] != ATypeTag.SERIALIZED_STRING_TYPE_TAG) {
             PointableHelper.setNull(result);
-            ExceptionUtil.warnTypeMismatch(context, sourceLoc, functionIdentifier, bytes[offset], 0, ATypeTag.STRING);
+            ExceptionUtil.warnTypeMismatch(context, srcLoc, funID, bytes[offset], 0, ATypeTag.STRING);
             return;
         }
         string.set(bytes, offset + 1, len - 1);
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/SubstringEval.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/SubstringEval.java
index 5d8b6ef..e8c2ff8 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/SubstringEval.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/SubstringEval.java
@@ -83,7 +83,7 @@
 
         byte[] bytes = argStart.getByteArray();
         int offset = argStart.getStartOffset();
-        if (!ArgumentUtils.checkWarnOrSetInteger(ctx, sourceLoc, functionIdentifier, 1, bytes, offset, mutableInt32)) {
+        if (!ArgumentUtils.setInteger(ctx, srcLoc, funID, 1, bytes, offset, mutableInt32)) {
             PointableHelper.setNull(result);
             return;
         }
@@ -91,7 +91,7 @@
 
         bytes = argLen.getByteArray();
         offset = argLen.getStartOffset();
-        if (!ArgumentUtils.checkWarnOrSetInteger(ctx, sourceLoc, functionIdentifier, 2, bytes, offset, mutableInt32)) {
+        if (!ArgumentUtils.setInteger(ctx, srcLoc, funID, 2, bytes, offset, mutableInt32)) {
             PointableHelper.setNull(result);
             return;
         }
@@ -102,7 +102,7 @@
         int length = argString.getLength();
         if (bytes[offset] != ATypeTag.SERIALIZED_STRING_TYPE_TAG) {
             PointableHelper.setNull(result);
-            ExceptionUtil.warnTypeMismatch(ctx, sourceLoc, functionIdentifier, bytes[offset], 0, ATypeTag.STRING);
+            ExceptionUtil.warnTypeMismatch(ctx, srcLoc, funID, bytes[offset], 0, ATypeTag.STRING);
             return;
         }
         string.set(bytes, offset + 1, length - 1);
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/bitwise/AbstractBitMultipleValuesEvaluator.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/bitwise/AbstractBitMultipleValuesEvaluator.java
index 1f9e046..3f0f854 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/bitwise/AbstractBitMultipleValuesEvaluator.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/bitwise/AbstractBitMultipleValuesEvaluator.java
@@ -116,14 +116,13 @@
 
         // Type and value validity check
         if (!PointableHelper.isValidLongValue(bytes, startOffset, true)) {
-            ExceptionUtil.warnTypeMismatch(context, sourceLoc, functionIdentifier, bytes[startOffset], 0,
-                    ATypeTag.BIGINT);
+            ExceptionUtil.warnTypeMismatch(context, srcLoc, funID, bytes[startOffset], 0, ATypeTag.BIGINT);
             PointableHelper.setNull(result);
             return;
         }
 
         // Result holder
-        long longResult = ATypeHierarchy.getLongValue(functionIdentifier.getName(), 0, bytes, startOffset);
+        long longResult = ATypeHierarchy.getLongValue(funID.getName(), 0, bytes, startOffset);
 
         // Loop and do the bitwise operation for all the arguments (start from index 1, we did first argument above)
         for (int i = 1; i < argPointables.length; i++) {
@@ -132,13 +131,12 @@
 
             // Type and value validity check
             if (!PointableHelper.isValidLongValue(bytes, startOffset, true)) {
-                ExceptionUtil.warnTypeMismatch(context, sourceLoc, functionIdentifier, bytes[startOffset], i,
-                        ATypeTag.BIGINT);
+                ExceptionUtil.warnTypeMismatch(context, srcLoc, funID, bytes[startOffset], i, ATypeTag.BIGINT);
                 PointableHelper.setNull(result);
                 return;
             }
 
-            long nextValue = ATypeHierarchy.getLongValue(functionIdentifier.getName(), i, bytes, startOffset);
+            long nextValue = ATypeHierarchy.getLongValue(funID.getName(), i, bytes, startOffset);
             longResult = applyBitwiseOperation(longResult, nextValue);
         }
 
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/bitwise/AbstractBitSingleValueEvaluator.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/bitwise/AbstractBitSingleValueEvaluator.java
index b212310..5c4b956 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/bitwise/AbstractBitSingleValueEvaluator.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/bitwise/AbstractBitSingleValueEvaluator.java
@@ -85,13 +85,12 @@
 
         // Validity check
         if (!PointableHelper.isValidLongValue(bytes, startOffset, true)) {
-            ExceptionUtil.warnTypeMismatch(context, sourceLoc, functionIdentifier, bytes[startOffset], 0,
-                    ATypeTag.BIGINT);
+            ExceptionUtil.warnTypeMismatch(context, srcLoc, funID, bytes[startOffset], 0, ATypeTag.BIGINT);
             PointableHelper.setNull(result);
             return;
         }
 
-        long longValue = ATypeHierarchy.getLongValue(functionIdentifier.getName(), 0, bytes, startOffset);
+        long longValue = ATypeHierarchy.getLongValue(funID.getName(), 0, bytes, startOffset);
         applyBitwiseOperation(longValue);
 
         writeResult(result);
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/bitwise/AbstractBitValuePositionEvaluator.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/bitwise/AbstractBitValuePositionEvaluator.java
index cdf77e8..031445d 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/bitwise/AbstractBitValuePositionEvaluator.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/bitwise/AbstractBitValuePositionEvaluator.java
@@ -126,8 +126,7 @@
 
         // Type and value validity check
         if (!PointableHelper.isValidLongValue(valueBytes, valueStartOffset, true)) {
-            ExceptionUtil.warnTypeMismatch(context, sourceLoc, functionIdentifier, valueBytes[valueStartOffset], 0,
-                    ATypeTag.BIGINT);
+            ExceptionUtil.warnTypeMismatch(context, srcLoc, funID, valueBytes[valueStartOffset], 0, ATypeTag.BIGINT);
             PointableHelper.setNull(result);
             return;
         }
@@ -140,14 +139,14 @@
 
         // Type validity check (for position argument, array is a valid type as well)
         if (!ATypeHierarchy.canPromote(positionTypeTag, ATypeTag.DOUBLE) && positionTypeTag != ATypeTag.ARRAY) {
-            ExceptionUtil.warnTypeMismatch(context, sourceLoc, functionIdentifier, positionBytes[positionStartOffset],
-                    1, secondArgumentExpectedTypes);
+            ExceptionUtil.warnTypeMismatch(context, srcLoc, funID, positionBytes[positionStartOffset], 1,
+                    secondArgumentExpectedTypes);
             PointableHelper.setNull(result);
             return;
         }
 
         // Result long value
-        longResult = ATypeHierarchy.getLongValue(functionIdentifier.getName(), 0, valueBytes, valueStartOffset);
+        longResult = ATypeHierarchy.getLongValue(funID.getName(), 0, valueBytes, valueStartOffset);
 
         // If any operation returns false, the result should be null
         boolean isSuccessfulOperation;
@@ -222,12 +221,11 @@
 
         // Value validity check
         if (!PointableHelper.isValidLongValue(bytes, startOffset, true)) {
-            ExceptionUtil.warnTypeMismatch(context, sourceLoc, functionIdentifier, bytes[startOffset], 1,
-                    ATypeTag.BIGINT);
+            ExceptionUtil.warnTypeMismatch(context, srcLoc, funID, bytes[startOffset], 1, ATypeTag.BIGINT);
             return false;
         }
 
-        long position = ATypeHierarchy.getLongValue(functionIdentifier.getName(), 1, bytes, startOffset);
+        long position = ATypeHierarchy.getLongValue(funID.getName(), 1, bytes, startOffset);
 
         // Ensure the position is between 1 and 64 (int64 has 64 bits)
         if (position < 1 || position > 64) {
@@ -243,7 +241,7 @@
     private void handleOutOfRangeInput(int inputPosition, int startLimit, int endLimit, long actual) {
         IWarningCollector warningCollector = context.getWarningCollector();
         if (warningCollector.shouldWarn()) {
-            warningCollector.warn(WarningUtil.forAsterix(sourceLoc, ErrorCode.VALUE_OUT_OF_RANGE, functionIdentifier,
+            warningCollector.warn(WarningUtil.forAsterix(srcLoc, ErrorCode.VALUE_OUT_OF_RANGE, funID,
                     ExceptionUtil.indexToPosition(inputPosition), startLimit, endLimit, actual));
         }
     }
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/bitwise/BitValueCountFlagEvaluator.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/bitwise/BitValueCountFlagEvaluator.java
index c5851b2..343066e 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/bitwise/BitValueCountFlagEvaluator.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/bitwise/BitValueCountFlagEvaluator.java
@@ -116,8 +116,7 @@
 
         // Type and value validity check
         if (!PointableHelper.isValidLongValue(valueBytes, valueStartOffset, true)) {
-            ExceptionUtil.warnTypeMismatch(context, sourceLoc, functionIdentifier, valueBytes[valueStartOffset], 0,
-                    ATypeTag.BIGINT);
+            ExceptionUtil.warnTypeMismatch(context, srcLoc, funID, valueBytes[valueStartOffset], 0, ATypeTag.BIGINT);
             PointableHelper.setNull(result);
             return;
         }
@@ -128,8 +127,7 @@
 
         // Type and Value validity check
         if (!PointableHelper.isValidLongValue(countBytes, countStartOffset, true)) {
-            ExceptionUtil.warnTypeMismatch(context, sourceLoc, functionIdentifier, countBytes[countStartOffset], 1,
-                    ATypeTag.BIGINT);
+            ExceptionUtil.warnTypeMismatch(context, srcLoc, funID, countBytes[countStartOffset], 1, ATypeTag.BIGINT);
             PointableHelper.setNull(result);
             return;
         }
@@ -142,8 +140,7 @@
             ATypeTag flagTypeTag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(flagBytes[flagStartOffset]);
 
             if (flagTypeTag != ATypeTag.BOOLEAN) {
-                ExceptionUtil.warnTypeMismatch(context, sourceLoc, functionIdentifier, flagBytes[flagStartOffset], 2,
-                        ATypeTag.BOOLEAN);
+                ExceptionUtil.warnTypeMismatch(context, srcLoc, funID, flagBytes[flagStartOffset], 2, ATypeTag.BOOLEAN);
                 PointableHelper.setNull(result);
                 return;
             }
@@ -152,8 +149,8 @@
         }
 
         // Result holder and count
-        long longValue = ATypeHierarchy.getLongValue(functionIdentifier.getName(), 0, valueBytes, valueStartOffset);
-        long count = ATypeHierarchy.getLongValue(functionIdentifier.getName(), 1, countBytes, countStartOffset);
+        long longValue = ATypeHierarchy.getLongValue(funID.getName(), 0, valueBytes, valueStartOffset);
+        long count = ATypeHierarchy.getLongValue(funID.getName(), 1, countBytes, countStartOffset);
 
         // Positive value is left shifting, negative value is right shifting, rotate if needed, do nothing on 0 count
         // Note, when rotating, for each 64 bits, the rotation is repeated, so rotating by 1 is same as rotating by 65,
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/bitwise/BitValuePositionFlagEvaluator.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/bitwise/BitValuePositionFlagEvaluator.java
index 4c41515..379d70f 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/bitwise/BitValuePositionFlagEvaluator.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/bitwise/BitValuePositionFlagEvaluator.java
@@ -148,8 +148,7 @@
 
         // Type and value validity check
         if (!PointableHelper.isValidLongValue(valueBytes, valueStartOffset, true)) {
-            ExceptionUtil.warnTypeMismatch(context, sourceLoc, functionIdentifier, valueBytes[valueStartOffset], 0,
-                    ATypeTag.BIGINT);
+            ExceptionUtil.warnTypeMismatch(context, srcLoc, funID, valueBytes[valueStartOffset], 0, ATypeTag.BIGINT);
             PointableHelper.setNull(result);
             return;
         }
@@ -162,8 +161,8 @@
 
         // Type validity check (for position argument, array is a valid type as well)
         if (!ATypeHierarchy.canPromote(positionTypeTag, ATypeTag.DOUBLE) && positionTypeTag != ATypeTag.ARRAY) {
-            ExceptionUtil.warnTypeMismatch(context, sourceLoc, functionIdentifier, positionBytes[positionStartOffset],
-                    1, secondArgumentExpectedTypes);
+            ExceptionUtil.warnTypeMismatch(context, srcLoc, funID, positionBytes[positionStartOffset], 1,
+                    secondArgumentExpectedTypes);
             PointableHelper.setNull(result);
             return;
         }
@@ -177,8 +176,7 @@
             ATypeTag flagTypeTag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(flagBytes[flagStartOffset]);
 
             if (flagTypeTag != ATypeTag.BOOLEAN) {
-                ExceptionUtil.warnTypeMismatch(context, sourceLoc, functionIdentifier, flagBytes[flagStartOffset], 2,
-                        ATypeTag.BOOLEAN);
+                ExceptionUtil.warnTypeMismatch(context, srcLoc, funID, flagBytes[flagStartOffset], 2, ATypeTag.BOOLEAN);
                 PointableHelper.setNull(result);
                 return;
             }
@@ -187,7 +185,7 @@
         }
 
         // Result long value
-        long longResult = ATypeHierarchy.getLongValue(functionIdentifier.getName(), 0, valueBytes, valueStartOffset);
+        long longResult = ATypeHierarchy.getLongValue(funID.getName(), 0, valueBytes, valueStartOffset);
 
         // If any operation returns false, the result should be null
         boolean isSuccessfulOperation;
@@ -271,12 +269,11 @@
 
         // Value validity check
         if (!PointableHelper.isValidLongValue(bytes, startOffset, true)) {
-            ExceptionUtil.warnTypeMismatch(context, sourceLoc, functionIdentifier, bytes[startOffset], 1,
-                    ATypeTag.BIGINT);
+            ExceptionUtil.warnTypeMismatch(context, srcLoc, funID, bytes[startOffset], 1, ATypeTag.BIGINT);
             return false;
         }
 
-        long position = ATypeHierarchy.getLongValue(functionIdentifier.getName(), 1, bytes, startOffset);
+        long position = ATypeHierarchy.getLongValue(funID.getName(), 1, bytes, startOffset);
 
         // Ensure the position is between 1 and 64 (int64 has 64 bits)
         if (position < 1 || position > 64) {
@@ -295,7 +292,7 @@
     private void handleOutOfRangeInput(int inputPosition, int startLimit, int endLimit, long actual) {
         IWarningCollector warningCollector = context.getWarningCollector();
         if (warningCollector.shouldWarn()) {
-            warningCollector.warn(WarningUtil.forAsterix(sourceLoc, ErrorCode.VALUE_OUT_OF_RANGE, functionIdentifier,
+            warningCollector.warn(WarningUtil.forAsterix(srcLoc, ErrorCode.VALUE_OUT_OF_RANGE, funID,
                     ExceptionUtil.indexToPosition(inputPosition), startLimit, endLimit, actual));
         }
     }
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/records/RecordMergeEvaluator.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/records/RecordMergeEvaluator.java
index 21b4040..95003a3 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/records/RecordMergeEvaluator.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/records/RecordMergeEvaluator.java
@@ -167,7 +167,7 @@
                     else {
                         // Ignore and take left field if ignore duplicate flag is true, otherwise, throw an exception
                         if (!isIgnoreDuplicates) {
-                            throw new RuntimeDataException(ErrorCode.DUPLICATE_FIELD_NAME, functionIdentifier);
+                            throw new RuntimeDataException(ErrorCode.DUPLICATE_FIELD_NAME, funID);
                         }
                     }
                 }