[ASTERIXDB-2603][FUN] Add compile/runtime warnings for bitwise functions

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

Details:
- Added compile/runtime warnings for bitwise functions.
- Added a new error code to represent values out of acceptable
range.

Change-Id: I9ada529d91d8fdc881447e8b4cf17fc8e71aa87f
Reviewed-on: https://asterix-gerrit.ics.uci.edu/3504
Contrib: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Sonar-Qube: 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: Michael Blow <mblow@apache.org>
diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java
index e172b38..188ad94 100644
--- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java
+++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java
@@ -75,6 +75,7 @@
     public static final int NO_STATEMENT_PROVIDED = 40;
     public static final int REQUEST_CANCELLED = 41;
     public static final int TPCDS_INVALID_TABLE_NAME = 42;
+    public static final int VALUE_OUT_OF_RANGE = 43;
 
     public static final int UNSUPPORTED_JRE = 100;
 
diff --git a/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties b/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties
index f8262d9..0848f66 100644
--- a/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties
+++ b/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties
@@ -77,6 +77,7 @@
 40 = No statement provided
 41 = Request %1$s has been cancelled
 42 = %1$s: \"%2$s\" is not a TPC-DS table name
+43 = Value out of range, function %1$s expects its %2$s input parameter value to be between %3$s and %4$s, received %5$s
 
 100 = Unsupported JRE: %1$s
 
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 437dda7..a9f9ea8 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
@@ -19,13 +19,17 @@
 
 package org.apache.asterix.runtime.evaluators.functions.bitwise;
 
+import org.apache.asterix.common.exceptions.ErrorCode;
+import org.apache.asterix.common.exceptions.WarningUtil;
 import org.apache.asterix.formats.nontagged.SerializerDeserializerProvider;
 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.asterix.runtime.evaluators.functions.AbstractScalarEval;
 import org.apache.asterix.runtime.evaluators.functions.PointableHelper;
+import org.apache.asterix.runtime.exceptions.ExceptionUtil;
 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;
@@ -65,10 +69,14 @@
     private final ISerializerDeserializer aInt64Serde =
             SerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.AINT64);
 
+    private final IEvaluatorContext context;
+
     AbstractBitMultipleValuesEvaluator(IEvaluatorContext context, IScalarEvaluatorFactory[] argEvaluatorFactories,
             FunctionIdentifier functionIdentifier, SourceLocation sourceLocation) throws HyracksDataException {
         super(sourceLocation, functionIdentifier);
 
+        this.context = context;
+
         // Evaluators and Pointables
         argPointables = new IPointable[argEvaluatorFactories.length];
         argEvaluators = new IScalarEvaluator[argEvaluatorFactories.length];
@@ -111,6 +119,7 @@
 
         // Type and value validity check
         if (!PointableHelper.isValidLongValue(bytes, startOffset, true)) {
+            handleTypeMismatchInput(0, ATypeTag.BIGINT, bytes, startOffset);
             PointableHelper.setNull(result);
             return;
         }
@@ -125,6 +134,7 @@
 
             // Type and value validity check
             if (!PointableHelper.isValidLongValue(bytes, startOffset, true)) {
+                handleTypeMismatchInput(i, ATypeTag.BIGINT, bytes, startOffset);
                 PointableHelper.setNull(result);
                 return;
             }
@@ -139,4 +149,10 @@
         aInt64Serde.serialize(resultMutableInt64, resultStorage.getDataOutput());
         result.set(resultStorage);
     }
+
+    private void handleTypeMismatchInput(int inputPosition, ATypeTag expected, byte[] bytes, int startOffset) {
+        ATypeTag actual = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(bytes[startOffset]);
+        context.getWarningCollector().warn(WarningUtil.forAsterix(sourceLoc, ErrorCode.TYPE_MISMATCH_FUNCTION,
+                functionIdentifier, ExceptionUtil.indexToPosition(inputPosition), expected, actual));
+    }
 }
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 425f336..d37d726 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
@@ -19,9 +19,14 @@
 
 package org.apache.asterix.runtime.evaluators.functions.bitwise;
 
+import org.apache.asterix.common.exceptions.ErrorCode;
+import org.apache.asterix.common.exceptions.WarningUtil;
+import org.apache.asterix.om.types.ATypeTag;
+import org.apache.asterix.om.types.EnumDeserializer;
 import org.apache.asterix.om.types.hierachy.ATypeHierarchy;
 import org.apache.asterix.runtime.evaluators.functions.AbstractScalarEval;
 import org.apache.asterix.runtime.evaluators.functions.PointableHelper;
+import org.apache.asterix.runtime.exceptions.ExceptionUtil;
 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;
@@ -54,10 +59,14 @@
     private final IScalarEvaluator valueEvaluator;
     private final IPointable valuePointable = VoidPointable.FACTORY.createPointable();
 
+    private final IEvaluatorContext context;
+
     AbstractBitSingleValueEvaluator(IEvaluatorContext context, IScalarEvaluatorFactory[] argEvaluatorFactories,
             FunctionIdentifier functionIdentifier, SourceLocation sourceLocation) throws HyracksDataException {
         super(sourceLocation, functionIdentifier);
 
+        this.context = context;
+
         // Evaluator
         valueEvaluator = argEvaluatorFactories[0].createScalarEvaluator(context);
     }
@@ -69,7 +78,6 @@
 
     @Override
     public void evaluate(IFrameTupleReference tuple, IPointable result) throws HyracksDataException {
-
         valueEvaluator.evaluate(tuple, valuePointable);
         if (PointableHelper.checkAndSetMissingOrNull(result, valuePointable)) {
             return;
@@ -80,6 +88,7 @@
 
         // Validity check
         if (!PointableHelper.isValidLongValue(bytes, startOffset, true)) {
+            handleTypeMismatchInput(0, ATypeTag.BIGINT, bytes, startOffset);
             PointableHelper.setNull(result);
             return;
         }
@@ -89,4 +98,10 @@
 
         writeResult(result);
     }
+
+    private void handleTypeMismatchInput(int inputPosition, ATypeTag expected, byte[] bytes, int startOffset) {
+        ATypeTag actual = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(bytes[startOffset]);
+        context.getWarningCollector().warn(WarningUtil.forAsterix(sourceLoc, ErrorCode.TYPE_MISMATCH_FUNCTION,
+                functionIdentifier, ExceptionUtil.indexToPosition(inputPosition), expected, actual));
+    }
 }
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 9d634c9..d1d3c93 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
@@ -21,6 +21,8 @@
 
 import java.io.IOException;
 
+import org.apache.asterix.common.exceptions.ErrorCode;
+import org.apache.asterix.common.exceptions.WarningUtil;
 import org.apache.asterix.formats.nontagged.SerializerDeserializerProvider;
 import org.apache.asterix.om.base.AMutableInt64;
 import org.apache.asterix.om.types.ATypeTag;
@@ -30,6 +32,7 @@
 import org.apache.asterix.runtime.evaluators.common.ListAccessor;
 import org.apache.asterix.runtime.evaluators.functions.AbstractScalarEval;
 import org.apache.asterix.runtime.evaluators.functions.PointableHelper;
+import org.apache.asterix.runtime.exceptions.ExceptionUtil;
 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;
@@ -89,9 +92,14 @@
     private final ISerializerDeserializer aInt64Serde =
             SerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.AINT64);
 
+    private final IEvaluatorContext context;
+    private static final byte[] secondArgumentExpectedTypes =
+            new byte[] { ATypeTag.SERIALIZED_INT64_TYPE_TAG, ATypeTag.SERIALIZED_ORDEREDLIST_TYPE_TAG };
+
     AbstractBitValuePositionEvaluator(IEvaluatorContext context, IScalarEvaluatorFactory[] argEvaluatorFactories,
             FunctionIdentifier functionIdentifier, SourceLocation sourceLocation) throws HyracksDataException {
         super(sourceLocation, functionIdentifier);
+        this.context = context;
 
         // Evaluators
         valueEvaluator = argEvaluatorFactories[0].createScalarEvaluator(context);
@@ -104,7 +112,6 @@
     @SuppressWarnings("unchecked")
     @Override
     public void evaluate(IFrameTupleReference tuple, IPointable result) throws HyracksDataException {
-
         valueEvaluator.evaluate(tuple, valuePointable);
         positionEvaluator.evaluate(tuple, positionPointable);
 
@@ -118,6 +125,7 @@
 
         // Type and value validity check
         if (!PointableHelper.isValidLongValue(valueBytes, valueStartOffset, true)) {
+            handleTypeMismatchInput(0, ATypeTag.BIGINT, valueBytes, valueStartOffset);
             PointableHelper.setNull(result);
             return;
         }
@@ -130,6 +138,7 @@
 
         // Type validity check (for position argument, array is a valid type as well)
         if (!ATypeHierarchy.canPromote(positionTypeTag, ATypeTag.DOUBLE) && positionTypeTag != ATypeTag.ARRAY) {
+            handleTypeMismatchInput(1, secondArgumentExpectedTypes, positionBytes, positionStartOffset);
             PointableHelper.setNull(result);
             return;
         }
@@ -210,6 +219,7 @@
 
         // Value validity check
         if (!PointableHelper.isValidLongValue(bytes, startOffset, true)) {
+            handleTypeMismatchInput(1, ATypeTag.BIGINT, bytes, startOffset);
             return false;
         }
 
@@ -217,6 +227,7 @@
 
         // Ensure the position is between 1 and 64 (int64 has 64 bits)
         if (position < 1 || position > 64) {
+            handleOutOfRangeInput(1, 1, 64, position);
             return false;
         }
 
@@ -224,4 +235,24 @@
 
         return true;
     }
+
+    private void handleTypeMismatchInput(int inputPosition, ATypeTag expected, byte[] actualBytes,
+            int actualStartOffset) {
+        ATypeTag actual = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(actualBytes[actualStartOffset]);
+        context.getWarningCollector().warn(WarningUtil.forAsterix(sourceLoc, ErrorCode.TYPE_MISMATCH_FUNCTION,
+                functionIdentifier, ExceptionUtil.indexToPosition(inputPosition), expected, actual));
+    }
+
+    private void handleTypeMismatchInput(int inputPosition, byte[] expected, byte[] bytes, int actualStartOffset) {
+        ATypeTag actual = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(bytes[actualStartOffset]);
+        context.getWarningCollector()
+                .warn(WarningUtil.forAsterix(sourceLoc, ErrorCode.TYPE_MISMATCH_FUNCTION, functionIdentifier,
+                        ExceptionUtil.indexToPosition(inputPosition), ExceptionUtil.toExpectedTypeString(expected),
+                        actual));
+    }
+
+    private void handleOutOfRangeInput(int inputPosition, int startLimit, int endLimit, long actual) {
+        context.getWarningCollector().warn(WarningUtil.forAsterix(sourceLoc, ErrorCode.VALUE_OUT_OF_RANGE,
+                functionIdentifier, 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 403387b..cc3033f 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
@@ -19,6 +19,8 @@
 
 package org.apache.asterix.runtime.evaluators.functions.bitwise;
 
+import org.apache.asterix.common.exceptions.ErrorCode;
+import org.apache.asterix.common.exceptions.WarningUtil;
 import org.apache.asterix.dataflow.data.nontagged.serde.ABooleanSerializerDeserializer;
 import org.apache.asterix.formats.nontagged.SerializerDeserializerProvider;
 import org.apache.asterix.om.base.AMutableInt64;
@@ -28,6 +30,7 @@
 import org.apache.asterix.om.types.hierachy.ATypeHierarchy;
 import org.apache.asterix.runtime.evaluators.functions.AbstractScalarEval;
 import org.apache.asterix.runtime.evaluators.functions.PointableHelper;
+import org.apache.asterix.runtime.exceptions.ExceptionUtil;
 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;
@@ -78,10 +81,14 @@
     private final ISerializerDeserializer aInt64Serde =
             SerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.AINT64);
 
+    private final IEvaluatorContext context;
+
     BitValueCountFlagEvaluator(IEvaluatorContext context, IScalarEvaluatorFactory[] argEvaluatorFactories,
             FunctionIdentifier functionIdentifier, SourceLocation sourceLocation) throws HyracksDataException {
         super(sourceLocation, functionIdentifier);
 
+        this.context = context;
+
         // Evaluator
         valueEvaluator = argEvaluatorFactories[0].createScalarEvaluator(context);
         countEvaluator = argEvaluatorFactories[1].createScalarEvaluator(context);
@@ -111,6 +118,7 @@
 
         // Type and value validity check
         if (!PointableHelper.isValidLongValue(valueBytes, valueStartOffset, true)) {
+            handleTypeMismatchInput(0, ATypeTag.BIGINT, valueBytes, valueStartOffset);
             PointableHelper.setNull(result);
             return;
         }
@@ -121,6 +129,7 @@
 
         // Type and Value validity check
         if (!PointableHelper.isValidLongValue(countBytes, countStartOffset, true)) {
+            handleTypeMismatchInput(1, ATypeTag.BIGINT, countBytes, countStartOffset);
             PointableHelper.setNull(result);
             return;
         }
@@ -133,6 +142,7 @@
             ATypeTag flagTypeTag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(flagBytes[flagStartOffset]);
 
             if (flagTypeTag != ATypeTag.BOOLEAN) {
+                handleTypeMismatchInput(2, ATypeTag.BOOLEAN, flagBytes, flagStartOffset);
                 PointableHelper.setNull(result);
                 return;
             }
@@ -157,7 +167,7 @@
 
         if (count < 0) {
             if (isRotate) {
-                longValue = Long.rotateRight(longValue, (int) Math.abs((count % -64)));
+                longValue = Long.rotateRight(longValue, (int) Math.abs(count % -64));
             } else {
                 longValue = longValue >> Math.abs(count);
             }
@@ -168,4 +178,10 @@
         aInt64Serde.serialize(resultMutableInt64, resultStorage.getDataOutput());
         result.set(resultStorage);
     }
+
+    private void handleTypeMismatchInput(int inputPosition, ATypeTag expected, byte[] bytes, int startOffset) {
+        ATypeTag actual = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(bytes[startOffset]);
+        context.getWarningCollector().warn(WarningUtil.forAsterix(sourceLoc, ErrorCode.TYPE_MISMATCH_FUNCTION,
+                functionIdentifier, ExceptionUtil.indexToPosition(inputPosition), expected, actual));
+    }
 }
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 fe7570e..85e033b 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
@@ -21,6 +21,8 @@
 
 import java.io.IOException;
 
+import org.apache.asterix.common.exceptions.ErrorCode;
+import org.apache.asterix.common.exceptions.WarningUtil;
 import org.apache.asterix.dataflow.data.nontagged.serde.ABooleanSerializerDeserializer;
 import org.apache.asterix.formats.nontagged.SerializerDeserializerProvider;
 import org.apache.asterix.om.base.ABoolean;
@@ -31,6 +33,7 @@
 import org.apache.asterix.runtime.evaluators.common.ListAccessor;
 import org.apache.asterix.runtime.evaluators.functions.AbstractScalarEval;
 import org.apache.asterix.runtime.evaluators.functions.PointableHelper;
+import org.apache.asterix.runtime.exceptions.ExceptionUtil;
 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;
@@ -104,10 +107,16 @@
     private final ISerializerDeserializer aBooleanSerde =
             SerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.ABOOLEAN);
 
+    private final IEvaluatorContext context;
+    private static final byte[] secondArgumentExpectedTypes =
+            new byte[] { ATypeTag.SERIALIZED_INT64_TYPE_TAG, ATypeTag.SERIALIZED_ORDEREDLIST_TYPE_TAG };
+
     BitValuePositionFlagEvaluator(IEvaluatorContext context, IScalarEvaluatorFactory[] argEvaluatorFactories,
             FunctionIdentifier functionIdentifier, SourceLocation sourceLocation) throws HyracksDataException {
         super(sourceLocation, functionIdentifier);
 
+        this.context = context;
+
         // Evaluators
         valueEvaluator = argEvaluatorFactories[0].createScalarEvaluator(context);
         positionEvaluator = argEvaluatorFactories[1].createScalarEvaluator(context);
@@ -121,7 +130,6 @@
     @SuppressWarnings("unchecked")
     @Override
     public void evaluate(IFrameTupleReference tuple, IPointable result) throws HyracksDataException {
-
         valueEvaluator.evaluate(tuple, valuePointable);
         positionEvaluator.evaluate(tuple, positionPointable);
 
@@ -139,6 +147,7 @@
 
         // Type and value validity check
         if (!PointableHelper.isValidLongValue(valueBytes, valueStartOffset, true)) {
+            handleTypeMismatchInput(0, ATypeTag.BIGINT, valueBytes, valueStartOffset);
             PointableHelper.setNull(result);
             return;
         }
@@ -151,6 +160,7 @@
 
         // Type validity check (for position argument, array is a valid type as well)
         if (!ATypeHierarchy.canPromote(positionTypeTag, ATypeTag.DOUBLE) && positionTypeTag != ATypeTag.ARRAY) {
+            handleTypeMismatchInput(1, secondArgumentExpectedTypes, positionBytes, positionStartOffset);
             PointableHelper.setNull(result);
             return;
         }
@@ -163,6 +173,7 @@
             ATypeTag flagTypeTag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(flagBytes[flagStartOffset]);
 
             if (flagTypeTag != ATypeTag.BOOLEAN) {
+                handleTypeMismatchInput(2, ATypeTag.BOOLEAN, flagBytes, flagStartOffset);
                 PointableHelper.setNull(result);
                 return;
             }
@@ -255,6 +266,7 @@
 
         // Value validity check
         if (!PointableHelper.isValidLongValue(bytes, startOffset, true)) {
+            handleTypeMismatchInput(1, ATypeTag.BIGINT, bytes, startOffset);
             return false;
         }
 
@@ -262,6 +274,7 @@
 
         // Ensure the position is between 1 and 64 (int64 has 64 bits)
         if (position < 1 || position > 64) {
+            handleOutOfRangeInput(1, 1, 64, position);
             return false;
         }
 
@@ -272,4 +285,24 @@
 
         return true;
     }
+
+    private void handleTypeMismatchInput(int inputPosition, ATypeTag expected, byte[] actualBytes,
+            int actualStartOffset) {
+        ATypeTag actual = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(actualBytes[actualStartOffset]);
+        context.getWarningCollector().warn(WarningUtil.forAsterix(sourceLoc, ErrorCode.TYPE_MISMATCH_FUNCTION,
+                functionIdentifier, ExceptionUtil.indexToPosition(inputPosition), expected, actual));
+    }
+
+    private void handleTypeMismatchInput(int inputPosition, byte[] expected, byte[] bytes, int actualStartOffset) {
+        ATypeTag actual = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(bytes[actualStartOffset]);
+        context.getWarningCollector()
+                .warn(WarningUtil.forAsterix(sourceLoc, ErrorCode.TYPE_MISMATCH_FUNCTION, functionIdentifier,
+                        ExceptionUtil.indexToPosition(inputPosition), ExceptionUtil.toExpectedTypeString(expected),
+                        actual));
+    }
+
+    private void handleOutOfRangeInput(int inputPosition, int startLimit, int endLimit, long actual) {
+        context.getWarningCollector().warn(WarningUtil.forAsterix(sourceLoc, ErrorCode.VALUE_OUT_OF_RANGE,
+                functionIdentifier, ExceptionUtil.indexToPosition(inputPosition), startLimit, endLimit, actual));
+    }
 }
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/exceptions/ExceptionUtil.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/exceptions/ExceptionUtil.java
index cf9ae22..b1e64dc 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/exceptions/ExceptionUtil.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/exceptions/ExceptionUtil.java
@@ -25,7 +25,7 @@
     private ExceptionUtil() {
     }
 
-    static String toExpectedTypeString(byte... expectedTypeTags) {
+    public static String toExpectedTypeString(byte... expectedTypeTags) {
         StringBuilder expectedTypes = new StringBuilder();
         int numCandidateTypes = expectedTypeTags.length;
         for (int index = 0; index < numCandidateTypes; ++index) {
@@ -41,7 +41,7 @@
         return expectedTypes.toString();
     }
 
-    static String indexToPosition(int index) {
+    public static String indexToPosition(int index) {
         int i = index + 1;
         switch (i % 100) {
             case 11: