You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@asterixdb.apache.org by al...@apache.org on 2019/11/21 17:33:48 UTC

[asterixdb] branch master updated: [ASTERIXDB-2634][FUN] String functions to return null on data/type errors

This is an automated email from the ASF dual-hosted git repository.

alsuliman pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/asterixdb.git


The following commit(s) were added to refs/heads/master by this push:
     new 69a7af4  [ASTERIXDB-2634][FUN] String functions to return null on data/type errors
69a7af4 is described below

commit 69a7af4725250edda18aa3b71b6851c11dd21d27
Author: Ali Alsuliman <al...@gmail.com>
AuthorDate: Wed Nov 20 16:26:12 2019 -0800

    [ASTERIXDB-2634][FUN] String functions to return null on data/type errors
    
    - user model changes: no
    - storage format changes: no
    - interface changes: no
    
    Details:
    - substring(string, int, int)
    - codepoint-to-string([int])
    - string-concat([string])
    
    Change-Id: I17905ad9e767b43822d28a46123bc1390a159cc7
    Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/4083
    Contrib: Jenkins <je...@fulliautomatix.ics.uci.edu>
    Integration-Tests: Jenkins <je...@fulliautomatix.ics.uci.edu>
    Tested-by: Jenkins <je...@fulliautomatix.ics.uci.edu>
    Reviewed-by: Hussain Towaileb <hu...@gmail.com>
---
 .../string_fun_004/string_fun_004.01.ddl.sqlpp     |  40 ++++++++
 .../string_fun_004/string_fun_004.02.update.sqlpp  |  30 ++++++
 .../string_fun_004/string_fun_004.03.query.sqlpp   |  36 +++++++
 .../string_fun_004/string_fun_004.04.query.sqlpp   |  36 +++++++
 .../string_fun_004/string_fun_004.05.query.sqlpp   |  35 +++++++
 .../string_fun_004/string_fun_004.06.ddl.sqlpp     |  20 ++++
 .../string_fun_004/string_fun_004.03.adm           |   2 +
 .../string_fun_004/string_fun_004.04.adm           |   2 +
 .../string_fun_004/string_fun_004.05.adm           |   1 +
 .../test/resources/runtimets/testsuite_sqlpp.xml   |  25 +++++
 .../serde/AOrderedListSerializerDeserializer.java  |   3 +
 .../asterix/om/functions/BuiltinFunctions.java     |  12 +--
 .../om/typecomputer/impl/AStringTypeComputer.java  |  13 +--
 .../om/typecomputer/impl/ConcatTypeComputer.java   |  16 +--
 ...er.java => Int64ArrayToStringTypeComputer.java} |  29 ++++--
 .../typecomputer/impl/SubstringTypeComputer.java   |  60 ------------
 .../functions/CodePointToStringDescriptor.java     | 107 ++++++++++++---------
 .../functions/StringConcatDescriptor.java          |  32 +++---
 .../evaluators/functions/SubstringEval.java        |  32 ++++--
 .../functions/binary/BinaryConcatDescriptor.java   |   1 +
 20 files changed, 367 insertions(+), 165 deletions(-)

diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fun_return_null/string_fun/string_fun_004/string_fun_004.01.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fun_return_null/string_fun/string_fun_004/string_fun_004.01.ddl.sqlpp
new file mode 100644
index 0000000..ac0c8ae
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fun_return_null/string_fun/string_fun_004/string_fun_004.01.ddl.sqlpp
@@ -0,0 +1,40 @@
+/*
+ * 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 dsType as {
+id:   int,
+i8:   int8,
+i16:  int16,
+i32:  int32,
+i64:  int64,
+f:    float,
+d:    double,
+str1: string
+};
+
+create type openType as {
+id: int
+};
+
+create dataset DS(dsType) primary key id;
+create dataset openDS(openType) primary key id;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fun_return_null/string_fun/string_fun_004/string_fun_004.02.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fun_return_null/string_fun/string_fun_004/string_fun_004.02.update.sqlpp
new file mode 100644
index 0000000..eea9d0c
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fun_return_null/string_fun/string_fun_004/string_fun_004.02.update.sqlpp
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+use test;
+
+insert into DS([
+{"id": 1, "i8": int8("-2"), "i16": int16("10"), "i32": int32("21"), "i64": int64("87"), "f": float("4.2"), "d": double("5.0"), "str1": "foo", "mixed": 7},
+{"id": 2, "i8": int8("0"), "i16": int16("-10"), "i32": int32("21"), "i64": int64("87"), "f": float("4.2"), "d": double("5.3"), "str1": "foo", "mixed": "m"}
+]);
+
+insert into openDS([
+{"id": 1, "i8": int8("-2"), "i16": int16("10"), "i32": int32("21"), "i64": int64("87"), "f": float("4.2"), "d": double("5.0"), "str1": "foo", "mixed": 7},
+{"id": 2, "i8": int8("0"), "i16": int16("-10"), "i32": int32("21"), "i64": int64("87"), "f": float("4.2"), "d": double("5.3"), "str1": "foo", "mixed": "m"}
+]);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fun_return_null/string_fun/string_fun_004/string_fun_004.03.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fun_return_null/string_fun/string_fun_004/string_fun_004.03.query.sqlpp
new file mode 100644
index 0000000..5ecc261
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fun_return_null/string_fun/string_fun_004/string_fun_004.03.query.sqlpp
@@ -0,0 +1,36 @@
+/*
+ * 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 that string functions do not throw exception on type/data errors
+ */
+// requesttype=application/json
+// param max-warnings:json=1000
+
+use test;
+
+from DS as ds
+select
+`string-concat`([ds.str1, ds.i8]),
+"str" || ds.mixed,
+substring("hello world", ds.str1, ds.i8),
+substring(ds.mixed, 0, 1),
+`codepoint-to-string`(ds.str1),
+`codepoint-to-string`([ds.mixed])
+order by ds.id;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fun_return_null/string_fun/string_fun_004/string_fun_004.04.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fun_return_null/string_fun/string_fun_004/string_fun_004.04.query.sqlpp
new file mode 100644
index 0000000..3042334
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fun_return_null/string_fun/string_fun_004/string_fun_004.04.query.sqlpp
@@ -0,0 +1,36 @@
+/*
+ * 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 that string functions do not throw exception on type/data errors
+ */
+// requesttype=application/json
+// param max-warnings:json=1000
+
+use test;
+
+from openDS as ds
+select
+`string-concat`([ds.str1, ds.i8]),
+"str" || ds.mixed,
+substring("hello world", ds.str1, ds.i8),
+substring(ds.mixed, 0, 1),
+`codepoint-to-string`(ds.str1),
+`codepoint-to-string`([ds.mixed])
+order by ds.id;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fun_return_null/string_fun/string_fun_004/string_fun_004.05.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fun_return_null/string_fun/string_fun_004/string_fun_004.05.query.sqlpp
new file mode 100644
index 0000000..6036007
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fun_return_null/string_fun/string_fun_004/string_fun_004.05.query.sqlpp
@@ -0,0 +1,35 @@
+/*
+ * 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 that string functions do not throw exception on type/data errors
+ */
+// requesttype=application/json
+// param max-warnings:json=1000
+
+use test;
+
+
+select
+`string-concat`(["str", 9]),
+"str" || int8("9"),
+substring("hello world", "str", 3),
+`codepoint-to-string`("str"),
+`codepoint-to-string`(["str"]),
+`codepoint-to-string`([5.5]);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fun_return_null/string_fun/string_fun_004/string_fun_004.06.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fun_return_null/string_fun/string_fun_004/string_fun_004.06.ddl.sqlpp
new file mode 100644
index 0000000..548e632
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fun_return_null/string_fun/string_fun_004/string_fun_004.06.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/string_fun/string_fun_004/string_fun_004.03.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/fun_return_null/string_fun/string_fun_004/string_fun_004.03.adm
new file mode 100644
index 0000000..2bc8a4b
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/fun_return_null/string_fun/string_fun_004/string_fun_004.03.adm
@@ -0,0 +1,2 @@
+{ "$1": null, "$2": null, "$3": null, "$4": null, "$5": null, "$6": "\u0007" }
+{ "$1": null, "$2": "strm", "$3": null, "$4": "m", "$5": null, "$6": null }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/fun_return_null/string_fun/string_fun_004/string_fun_004.04.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/fun_return_null/string_fun/string_fun_004/string_fun_004.04.adm
new file mode 100644
index 0000000..2bc8a4b
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/fun_return_null/string_fun/string_fun_004/string_fun_004.04.adm
@@ -0,0 +1,2 @@
+{ "$1": null, "$2": null, "$3": null, "$4": null, "$5": null, "$6": "\u0007" }
+{ "$1": null, "$2": "strm", "$3": null, "$4": "m", "$5": null, "$6": null }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/fun_return_null/string_fun/string_fun_004/string_fun_004.05.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/fun_return_null/string_fun/string_fun_004/string_fun_004.05.adm
new file mode 100644
index 0000000..c89e546
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/fun_return_null/string_fun/string_fun_004/string_fun_004.05.adm
@@ -0,0 +1 @@
+{ "$1": null, "$2": null, "$3": null, "$4": null, "$5": null, "$6": 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 3a0d50b..5bb68e0 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
@@ -13606,5 +13606,30 @@
         <expected-warn>Invalid value: function substring expects its 2nd input parameter to be an integer value, got Infinity (in line 34, at column 1)</expected-warn>
       </compilation-unit>
     </test-case>
+    <test-case FilePath="fun_return_null/string_fun" check-warnings="true">
+      <compilation-unit name="string_fun_004">
+        <output-dir compare="Text">string_fun_004</output-dir>
+        <expected-warn>Unsupported type: string-concat cannot process input type tinyint (in line 30, at column 1)</expected-warn>
+        <expected-warn>Type mismatch: function substring expects its 2nd input parameter to be of type tinyint, smallint, integer, bigint, float or double, but the actual input type is string (in line 32, at column 1)</expected-warn>
+        <expected-warn>Type mismatch: function substring expects its 1st input parameter to be of type string, but the actual input type is bigint (in line 33, at column 1)</expected-warn>
+        <expected-warn>Unsupported type: string-concat cannot process input type bigint (in line 31, at column 7)</expected-warn>
+        <expected-warn>Type mismatch: function codepoint-to-string expects its 1st input parameter to be of type array, but the actual input type is string (in line 34, at column 1)</expected-warn>
+        <expected-warn>Unsupported type: codepoint-to-string cannot process input type string (in line 35, at column 1)</expected-warn>
+
+        <expected-warn>Unsupported type: string-concat cannot process input type tinyint (in line 30, at column 1)</expected-warn>
+        <expected-warn>Type mismatch: function substring expects its 2nd input parameter to be of type tinyint, smallint, integer, bigint, float or double, but the actual input type is string (in line 32, at column 1)</expected-warn>
+        <expected-warn>Type mismatch: function substring expects its 1st input parameter to be of type string, but the actual input type is bigint (in line 33, at column 1)</expected-warn>
+        <expected-warn>Unsupported type: string-concat cannot process input type bigint (in line 31, at column 7)</expected-warn>
+        <expected-warn>Type mismatch: function codepoint-to-string expects its 1st input parameter to be of type array, but the actual input type is string (in line 34, at column 1)</expected-warn>
+        <expected-warn>Unsupported type: codepoint-to-string cannot process input type string (in line 35, at column 1)</expected-warn>
+
+        <expected-warn>Unsupported type: string-concat cannot process input type bigint (in line 30, at column 1)</expected-warn>
+        <expected-warn>Unsupported type: string-concat cannot process input type tinyint (in line 31, at column 7)</expected-warn>
+        <expected-warn>Type mismatch: function substring expects its 1st input parameter to be of type string, but the actual input type is bigint (in line 32, at column 1)</expected-warn>
+        <expected-warn>Type mismatch: function codepoint-to-string expects its 1st input parameter to be of type array, but the actual input type is string (in line 33, at column 1)</expected-warn>
+        <expected-warn>Unsupported type: codepoint-to-string cannot process input type string (in line 34, at column 1)</expected-warn>
+        <expected-warn>Unsupported type: codepoint-to-string cannot process input type double (in line 35, at column 1)</expected-warn>
+      </compilation-unit>
+    </test-case>
   </test-group>
 </test-suite>
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/serde/AOrderedListSerializerDeserializer.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/serde/AOrderedListSerializerDeserializer.java
index bffc3b2..e443e13 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/serde/AOrderedListSerializerDeserializer.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/serde/AOrderedListSerializerDeserializer.java
@@ -116,15 +116,18 @@ public class AOrderedListSerializerDeserializer implements ISerializerDeserializ
         listBuilder.write(out, false);
     }
 
+    /** {@code serOrderedList} is untagged. {@code offset} points to the list value (first byte is the item tag) */
     public static int getOrderedListLength(byte[] serOrderedList, int offset) {
         return AInt32SerializerDeserializer.getInt(serOrderedList, offset + 1);
     }
 
+    /** {@code serOrderedList} is tagged. {@code offset} points to the list tag */
     public static int getNumberOfItems(byte[] serOrderedList, int offset) {
         // 6 = tag (1) + itemTag (1) + list size (4)
         return AInt32SerializerDeserializer.getInt(serOrderedList, offset + 6);
     }
 
+    /** {@code serOrderedList} is tagged. {@code offset} points to the list tag */
     public static int getItemOffset(byte[] serOrderedList, int offset, int itemIndex) throws HyracksDataException {
         return SerializerDeserializerUtil.getItemOffset(serOrderedList, offset, itemIndex);
     }
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 b6c1bf4..53ed003 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
@@ -94,6 +94,7 @@ import org.apache.asterix.om.typecomputer.impl.IfMissingTypeComputer;
 import org.apache.asterix.om.typecomputer.impl.IfNanOrInfTypeComputer;
 import org.apache.asterix.om.typecomputer.impl.IfNullTypeComputer;
 import org.apache.asterix.om.typecomputer.impl.InjectFailureTypeComputer;
+import org.apache.asterix.om.typecomputer.impl.Int64ArrayToStringTypeComputer;
 import org.apache.asterix.om.typecomputer.impl.LocalAvgTypeComputer;
 import org.apache.asterix.om.typecomputer.impl.LocalSingleVarStatisticsTypeComputer;
 import org.apache.asterix.om.typecomputer.impl.MinMaxAggTypeComputer;
@@ -127,7 +128,6 @@ import org.apache.asterix.om.typecomputer.impl.ScalarVersionOfAggregateResultTyp
 import org.apache.asterix.om.typecomputer.impl.SleepTypeComputer;
 import org.apache.asterix.om.typecomputer.impl.StringJoinTypeComputer;
 import org.apache.asterix.om.typecomputer.impl.SubsetCollectionTypeComputer;
-import org.apache.asterix.om.typecomputer.impl.SubstringTypeComputer;
 import org.apache.asterix.om.typecomputer.impl.SwitchCaseComputer;
 import org.apache.asterix.om.typecomputer.impl.ToArrayTypeComputer;
 import org.apache.asterix.om.typecomputer.impl.ToBigIntTypeComputer;
@@ -1709,14 +1709,14 @@ public class BuiltinFunctions {
         addFunction(IS_BIT_SET_WITH_ALL_FLAG, BitValuePositionFlagTypeComputer.INSTANCE_TEST_WITH_FLAG, true);
 
         // string functions
-        addFunction(STRING_CONSTRUCTOR, AStringTypeComputer.INSTANCE, true); // TODO
+        addFunction(STRING_CONSTRUCTOR, AStringTypeComputer.INSTANCE, true); // TODO(ali)
         addFunction(STRING_LIKE, BooleanFunctionTypeComputer.INSTANCE, true);
         addFunction(STRING_CONTAINS, UniformInputTypeComputer.STRING_BOOLEAN_INSTANCE, true);
         addFunction(STRING_TO_CODEPOINT, UniformInputTypeComputer.STRING_INT64_LIST_INSTANCE, true);
-        addFunction(CODEPOINT_TO_STRING, AStringTypeComputer.INSTANCE, true); // TODO
-        addFunction(STRING_CONCAT, ConcatTypeComputer.INSTANCE_STRING, true); // TODO
-        addFunction(SUBSTRING, SubstringTypeComputer.INSTANCE, true); // TODO
-        addFunction(SUBSTRING_OFFSET_1, SubstringTypeComputer.INSTANCE, true); // TODO
+        addFunction(CODEPOINT_TO_STRING, Int64ArrayToStringTypeComputer.INSTANCE, true);
+        addFunction(STRING_CONCAT, ConcatTypeComputer.INSTANCE_STRING, true);
+        addFunction(SUBSTRING, AStringTypeComputer.INSTANCE_NULLABLE, true);
+        addFunction(SUBSTRING_OFFSET_1, AStringTypeComputer.INSTANCE_NULLABLE, true);
         addFunction(SUBSTRING2, AStringTypeComputer.INSTANCE_NULLABLE, true);
         addFunction(SUBSTRING2_OFFSET_1, AStringTypeComputer.INSTANCE_NULLABLE, true);
         addFunction(STRING_LENGTH, UniformInputTypeComputer.STRING_INT64_INSTANCE, true);
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/AStringTypeComputer.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/AStringTypeComputer.java
index 4de96b8..d392e8d 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/AStringTypeComputer.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/AStringTypeComputer.java
@@ -27,17 +27,18 @@ import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
 
 public class AStringTypeComputer extends AbstractResultTypeComputer {
 
-    public static final AStringTypeComputer INSTANCE = new AStringTypeComputer(false);
-    public static final AStringTypeComputer INSTANCE_NULLABLE = new AStringTypeComputer(true);
+    public static final AStringTypeComputer INSTANCE = new AStringTypeComputer(BuiltinType.ASTRING);
+    public static final AStringTypeComputer INSTANCE_NULLABLE =
+            new AStringTypeComputer(AUnionType.createNullableType(BuiltinType.ASTRING));
 
-    private final boolean nullable;
+    private final IAType outputType;
 
-    private AStringTypeComputer(boolean nullable) {
-        this.nullable = nullable;
+    private AStringTypeComputer(IAType outputType) {
+        this.outputType = outputType;
     }
 
     @Override
     protected IAType getResultType(ILogicalExpression expr, IAType... strippedInputTypes) throws AlgebricksException {
-        return nullable ? AUnionType.createNullableType(BuiltinType.ASTRING) : BuiltinType.ASTRING;
+        return outputType;
     }
 }
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/ConcatTypeComputer.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/ConcatTypeComputer.java
index db59877..c13418f 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/ConcatTypeComputer.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/ConcatTypeComputer.java
@@ -43,22 +43,10 @@ public class ConcatTypeComputer extends AbstractResultTypeComputer {
     protected IAType getResultType(ILogicalExpression expr, IAType... strippedInputTypes) throws AlgebricksException {
         IAType argType = strippedInputTypes[0];
         IAType outputType = resultType;
-        if (!argType.getTypeTag().isListType() || isUnknownable(((AbstractCollectionType) argType).getItemType())) {
+        if (!argType.getTypeTag().isListType()
+                || ((AbstractCollectionType) argType).getItemType().getTypeTag() != outputType.getTypeTag()) {
             outputType = AUnionType.createUnknownableType(outputType);
         }
         return outputType;
     }
-
-    private boolean isUnknownable(IAType type) {
-        switch (type.getTypeTag()) {
-            case ANY:
-            case MISSING:
-            case NULL:
-                return true;
-            case UNION:
-                return ((AUnionType) type).isUnknownableType();
-            default:
-                return false;
-        }
-    }
 }
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/AStringTypeComputer.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/Int64ArrayToStringTypeComputer.java
similarity index 60%
copy from asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/AStringTypeComputer.java
copy to asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/Int64ArrayToStringTypeComputer.java
index 4de96b8..318297a 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/AStringTypeComputer.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/Int64ArrayToStringTypeComputer.java
@@ -16,28 +16,39 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+
 package org.apache.asterix.om.typecomputer.impl;
 
+import static org.apache.asterix.om.types.ATypeTag.ARRAY;
+import static org.apache.asterix.om.types.ATypeTag.BIGINT;
+
 import org.apache.asterix.om.typecomputer.base.AbstractResultTypeComputer;
 import org.apache.asterix.om.types.AUnionType;
+import org.apache.asterix.om.types.AbstractCollectionType;
 import org.apache.asterix.om.types.BuiltinType;
 import org.apache.asterix.om.types.IAType;
+import org.apache.asterix.om.types.hierachy.ATypeHierarchy;
 import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
 import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
 
-public class AStringTypeComputer extends AbstractResultTypeComputer {
-
-    public static final AStringTypeComputer INSTANCE = new AStringTypeComputer(false);
-    public static final AStringTypeComputer INSTANCE_NULLABLE = new AStringTypeComputer(true);
+/**
+ * For function signature: string fun([int64])
+ */
+public class Int64ArrayToStringTypeComputer extends AbstractResultTypeComputer {
 
-    private final boolean nullable;
+    public static final Int64ArrayToStringTypeComputer INSTANCE = new Int64ArrayToStringTypeComputer();
 
-    private AStringTypeComputer(boolean nullable) {
-        this.nullable = nullable;
+    private Int64ArrayToStringTypeComputer() {
     }
 
     @Override
     protected IAType getResultType(ILogicalExpression expr, IAType... strippedInputTypes) throws AlgebricksException {
-        return nullable ? AUnionType.createNullableType(BuiltinType.ASTRING) : BuiltinType.ASTRING;
+        IAType argType = strippedInputTypes[0];
+        return isValid(argType) ? BuiltinType.ASTRING : AUnionType.createUnknownableType(BuiltinType.ASTRING);
+    }
+
+    private static boolean isValid(IAType argType) {
+        return argType.getTypeTag() == ARRAY
+                && ATypeHierarchy.canPromote(((AbstractCollectionType) argType).getItemType().getTypeTag(), BIGINT);
     }
-}
+}
\ No newline at end of file
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/SubstringTypeComputer.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/SubstringTypeComputer.java
deleted file mode 100644
index ab0b159..0000000
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/SubstringTypeComputer.java
+++ /dev/null
@@ -1,60 +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.
- */
-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.AUnionType;
-import org.apache.asterix.om.types.BuiltinType;
-import org.apache.asterix.om.types.IAType;
-import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
-import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
-import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
-import org.apache.hyracks.api.exceptions.SourceLocation;
-
-public class SubstringTypeComputer extends AbstractResultTypeComputer {
-    public static final SubstringTypeComputer INSTANCE = new SubstringTypeComputer();
-
-    @Override
-    public void checkArgType(FunctionIdentifier funcId, int argIndex, IAType type, SourceLocation sourceLoc)
-            throws AlgebricksException {
-        ATypeTag tag = type.getTypeTag();
-        if (argIndex == 0 && tag != ATypeTag.STRING) {
-            throw new TypeMismatchException(sourceLoc, funcId, argIndex, tag, ATypeTag.STRING);
-        }
-        if (argIndex > 0 && argIndex <= 2) {
-            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
-    public IAType getResultType(ILogicalExpression expr, IAType... types) throws AlgebricksException {
-        return AUnionType.createNullableType(BuiltinType.ASTRING);
-    }
-}
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/CodePointToStringDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/CodePointToStringDescriptor.java
index c4317f9..fcfab72 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/CodePointToStringDescriptor.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/CodePointToStringDescriptor.java
@@ -18,19 +18,23 @@
  */
 package org.apache.asterix.runtime.evaluators.functions;
 
+import static org.apache.asterix.om.types.ATypeTag.BIGINT;
+import static org.apache.asterix.om.types.ATypeTag.MISSING;
+import static org.apache.asterix.om.types.ATypeTag.NULL;
+import static org.apache.asterix.om.types.ATypeTag.VALUE_TYPE_MAPPING;
+
 import java.io.DataOutput;
 import java.io.IOException;
+import java.util.Arrays;
 
 import org.apache.asterix.common.annotations.MissingNullInOutFunction;
 import org.apache.asterix.dataflow.data.nontagged.serde.AOrderedListSerializerDeserializer;
+import org.apache.asterix.om.exceptions.ExceptionUtil;
 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.hierachy.ATypeHierarchy;
 import org.apache.asterix.runtime.evaluators.base.AbstractScalarFunctionDynamicDescriptor;
-import org.apache.asterix.runtime.exceptions.TypeMismatchException;
-import org.apache.asterix.runtime.exceptions.UnsupportedTypeException;
 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;
@@ -46,12 +50,7 @@ import org.apache.hyracks.util.string.UTF8StringUtil;
 public class CodePointToStringDescriptor extends AbstractScalarFunctionDynamicDescriptor {
 
     private static final long serialVersionUID = 1L;
-    public static final IFunctionDescriptorFactory FACTORY = new IFunctionDescriptorFactory() {
-        @Override
-        public IFunctionDescriptor createFunctionDescriptor() {
-            return new CodePointToStringDescriptor();
-        }
-    };
+    public static final IFunctionDescriptorFactory FACTORY = CodePointToStringDescriptor::new;
 
     @Override
     public IScalarEvaluatorFactory createEvaluatorFactory(final IScalarEvaluatorFactory[] args) {
@@ -63,20 +62,21 @@ public class CodePointToStringDescriptor extends AbstractScalarFunctionDynamicDe
             public IScalarEvaluator createScalarEvaluator(IEvaluatorContext ctx) throws HyracksDataException {
                 return new IScalarEvaluator() {
 
-                    private ArrayBackedValueStorage resultStorage = new ArrayBackedValueStorage();
-                    private DataOutput out = resultStorage.getDataOutput();
-                    private IScalarEvaluatorFactory listEvalFactory = args[0];
-                    private IPointable inputArgList = new VoidPointable();
-                    private IScalarEvaluator evalList = listEvalFactory.createScalarEvaluator(ctx);
-
+                    private final ArrayBackedValueStorage resultStorage = new ArrayBackedValueStorage();
+                    private final DataOutput out = resultStorage.getDataOutput();
+                    private final IScalarEvaluatorFactory listEvalFactory = args[0];
+                    private final IPointable inputArgList = new VoidPointable();
+                    private final IScalarEvaluator evalList = listEvalFactory.createScalarEvaluator(ctx);
                     private final byte[] currentUTF8 = new byte[6];
                     private final byte[] tempStoreForLength = new byte[5];
-                    private final byte stringTypeTag = ATypeTag.SERIALIZED_STRING_TYPE_TAG;
+                    private final FunctionIdentifier fid = getIdentifier();
 
                     @Override
                     public void evaluate(IFrameTupleReference tuple, IPointable result) throws HyracksDataException {
                         try {
                             resultStorage.reset();
+                            Arrays.fill(tempStoreForLength, (byte) 0);
+                            Arrays.fill(currentUTF8, (byte) 0);
                             evalList.evaluate(tuple, inputArgList);
 
                             if (PointableHelper.checkAndSetMissingOrNull(result, inputArgList)) {
@@ -85,45 +85,63 @@ public class CodePointToStringDescriptor extends AbstractScalarFunctionDynamicDe
 
                             byte[] serOrderedList = inputArgList.getByteArray();
                             int offset = inputArgList.getStartOffset();
-                            int size;
-
-                            if (ATypeTag.VALUE_TYPE_MAPPING[serOrderedList[offset]] != ATypeTag.ARRAY) {
-                                throw new TypeMismatchException(sourceLoc, getIdentifier(), 0, serOrderedList[offset]);
-                            } else {
-                                switch (ATypeTag.VALUE_TYPE_MAPPING[serOrderedList[offset + 1]]) {
-                                    case TINYINT:
-                                    case SMALLINT:
-                                    case INTEGER:
-                                    case BIGINT:
-                                    case FLOAT:
-                                    case DOUBLE:
-                                    case ANY:
-                                        size = AOrderedListSerializerDeserializer.getNumberOfItems(serOrderedList,
-                                                offset);
-                                        break;
-                                    default:
-                                        throw new UnsupportedTypeException(sourceLoc, getIdentifier(),
-                                                serOrderedList[offset]);
-                                }
+                            if (serOrderedList[offset] != ATypeTag.SERIALIZED_ORDEREDLIST_TYPE_TAG) {
+                                PointableHelper.setNull(result);
+                                ExceptionUtil.warnTypeMismatch(ctx, sourceLoc, fid, serOrderedList[offset], 0,
+                                        ATypeTag.ARRAY);
+                                return;
                             }
+                            int itemTagPosition = offset + 1;
+                            ATypeTag itemTag = VALUE_TYPE_MAPPING[serOrderedList[itemTagPosition]];
+                            boolean isItemTagged = itemTag == ATypeTag.ANY;
+                            int size = AOrderedListSerializerDeserializer.getNumberOfItems(serOrderedList, offset);
                             // calculate length first
                             int utf_8_len = 0;
+                            boolean returnNull = false;
+                            ATypeTag invalidTag = null;
                             for (int i = 0; i < size; i++) {
                                 int itemOffset =
                                         AOrderedListSerializerDeserializer.getItemOffset(serOrderedList, offset, i);
-                                int codePoint = 0;
-                                codePoint = ATypeHierarchy.getIntegerValueWithDifferentTypeTagPosition(
-                                        getIdentifier().getName(), 0, serOrderedList, itemOffset, offset + 1);
-                                utf_8_len += UTF8StringUtil.codePointToUTF8(codePoint, currentUTF8);
+                                if (isItemTagged) {
+                                    itemTag = VALUE_TYPE_MAPPING[serOrderedList[itemOffset]];
+                                    itemTagPosition = itemOffset;
+                                    itemOffset++;
+                                }
+                                if (itemTag == MISSING) {
+                                    PointableHelper.setMissing(result);
+                                    return;
+                                }
+                                if (itemTag == NULL) {
+                                    returnNull = true;
+                                    invalidTag = null;
+                                } else if (!returnNull && !ATypeHierarchy.canPromote(itemTag, BIGINT)) {
+                                    returnNull = true;
+                                    invalidTag = itemTag;
+                                }
+                                if (!returnNull) {
+                                    int codePoint = ATypeHierarchy.getIntegerValueWithDifferentTypeTagPosition(
+                                            fid.getName(), 0, serOrderedList, itemOffset, itemTagPosition);
+                                    utf_8_len += UTF8StringUtil.codePointToUTF8(codePoint, currentUTF8);
+                                }
                             }
-                            out.writeByte(stringTypeTag);
+                            if (returnNull) {
+                                PointableHelper.setNull(result);
+                                if (invalidTag != null) {
+                                    ExceptionUtil.warnUnsupportedType(ctx, sourceLoc, fid.getName(), invalidTag);
+                                }
+                                return;
+                            }
+                            out.writeByte(ATypeTag.SERIALIZED_STRING_TYPE_TAG);
                             UTF8StringUtil.writeUTF8Length(utf_8_len, tempStoreForLength, out);
                             for (int i = 0; i < size; i++) {
                                 int itemOffset =
                                         AOrderedListSerializerDeserializer.getItemOffset(serOrderedList, offset, i);
-                                int codePoint = 0;
-                                codePoint = ATypeHierarchy.getIntegerValueWithDifferentTypeTagPosition(
-                                        getIdentifier().getName(), 0, serOrderedList, itemOffset, offset + 1);
+                                if (isItemTagged) {
+                                    itemTagPosition = itemOffset;
+                                    itemOffset++;
+                                }
+                                int codePoint = ATypeHierarchy.getIntegerValueWithDifferentTypeTagPosition(
+                                        fid.getName(), 0, serOrderedList, itemOffset, itemTagPosition);
                                 utf_8_len = UTF8StringUtil.codePointToUTF8(codePoint, currentUTF8);
                                 for (int j = 0; j < utf_8_len; j++) {
                                     out.writeByte(currentUTF8[j]);
@@ -143,5 +161,4 @@ public class CodePointToStringDescriptor extends AbstractScalarFunctionDynamicDe
     public FunctionIdentifier getIdentifier() {
         return BuiltinFunctions.CODEPOINT_TO_STRING;
     }
-
 }
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/StringConcatDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/StringConcatDescriptor.java
index a3cbfa5..e16ab51 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/StringConcatDescriptor.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/StringConcatDescriptor.java
@@ -25,15 +25,13 @@ import org.apache.asterix.common.annotations.MissingNullInOutFunction;
 import org.apache.asterix.formats.nontagged.SerializerDeserializerProvider;
 import org.apache.asterix.om.base.AMissing;
 import org.apache.asterix.om.base.ANull;
+import org.apache.asterix.om.exceptions.ExceptionUtil;
 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.evaluators.common.ListAccessor;
-import org.apache.asterix.runtime.exceptions.TypeMismatchException;
-import org.apache.asterix.runtime.exceptions.UnsupportedItemTypeException;
 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;
@@ -50,12 +48,7 @@ import org.apache.hyracks.util.string.UTF8StringUtil;
 public class StringConcatDescriptor extends AbstractScalarFunctionDynamicDescriptor {
 
     private static final long serialVersionUID = 1L;
-    public static final IFunctionDescriptorFactory FACTORY = new IFunctionDescriptorFactory() {
-        @Override
-        public IFunctionDescriptor createFunctionDescriptor() {
-            return new StringConcatDescriptor();
-        }
-    };
+    public static final IFunctionDescriptorFactory FACTORY = StringConcatDescriptor::new;
 
     @Override
     public IScalarEvaluatorFactory createEvaluatorFactory(final IScalarEvaluatorFactory[] args) {
@@ -79,6 +72,8 @@ public class StringConcatDescriptor extends AbstractScalarFunctionDynamicDescrip
                     private ISerializerDeserializer<AMissing> missingSerde =
                             SerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.AMISSING);
                     private final byte[] tempLengthArray = new byte[5];
+                    private final byte[] expectedTypes = new byte[] { ATypeTag.SERIALIZED_ORDEREDLIST_TYPE_TAG,
+                            ATypeTag.SERIALIZED_UNORDEREDLIST_TYPE_TAG };
 
                     @Override
                     public void evaluate(IFrameTupleReference tuple, IPointable result) throws HyracksDataException {
@@ -95,14 +90,16 @@ public class StringConcatDescriptor extends AbstractScalarFunctionDynamicDescrip
 
                             if (listBytes[listOffset] != ATypeTag.SERIALIZED_ORDEREDLIST_TYPE_TAG
                                     && listBytes[listOffset] != ATypeTag.SERIALIZED_UNORDEREDLIST_TYPE_TAG) {
-                                throw new TypeMismatchException(sourceLoc, getIdentifier(), 0, listBytes[listOffset],
-                                        ATypeTag.SERIALIZED_ORDEREDLIST_TYPE_TAG,
-                                        ATypeTag.SERIALIZED_UNORDEREDLIST_TYPE_TAG);
+                                PointableHelper.setNull(result);
+                                ExceptionUtil.warnTypeMismatch(ctx, sourceLoc, getIdentifier(), listBytes[listOffset],
+                                        0, expectedTypes);
+                                return;
                             }
                             listAccessor.reset(listBytes, listOffset);
                             // calculate length first
                             int utf8Len = 0;
                             boolean itemIsNull = false;
+                            ATypeTag unsupportedType = null;
                             for (int i = 0; i < listAccessor.size(); i++) {
                                 int itemOffset = listAccessor.getItemOffset(i);
                                 ATypeTag itemType = listAccessor.getItemType(itemOffset);
@@ -121,14 +118,19 @@ public class StringConcatDescriptor extends AbstractScalarFunctionDynamicDescrip
                                         result.set(resultStorage);
                                         return;
                                     }
-                                    throw new UnsupportedItemTypeException(sourceLoc, getIdentifier(),
-                                            itemType.serialize());
+                                    if (unsupportedType == null) {
+                                        unsupportedType = itemType;
+                                    }
                                 }
                                 utf8Len += UTF8StringUtil.getUTFLength(listBytes, itemOffset);
                             }
-                            if (itemIsNull) {
+                            if (itemIsNull || unsupportedType != null) {
                                 nullSerde.serialize(ANull.NULL, out);
                                 result.set(resultStorage);
+                                if (unsupportedType != null) {
+                                    ExceptionUtil.warnUnsupportedType(ctx, sourceLoc, getIdentifier().getName(),
+                                            unsupportedType);
+                                }
                                 return;
                             }
                             out.writeByte(ATypeTag.SERIALIZED_STRING_TYPE_TAG);
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 993f5e6..5d8b6ef 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
@@ -22,9 +22,10 @@ import java.io.DataOutput;
 import java.io.IOException;
 
 import org.apache.asterix.common.annotations.MissingNullInOutFunction;
+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.hierachy.ATypeHierarchy;
-import org.apache.asterix.runtime.exceptions.TypeMismatchException;
+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;
@@ -44,9 +45,10 @@ class SubstringEval extends AbstractScalarEval {
 
     private final ArrayBackedValueStorage resultStorage = new ArrayBackedValueStorage();
     private final DataOutput out = resultStorage.getDataOutput();
-    private IPointable argString = new VoidPointable();
-    private IPointable argStart = new VoidPointable();
-    private IPointable argLen = new VoidPointable();
+    private final IPointable argString = new VoidPointable();
+    private final IPointable argStart = new VoidPointable();
+    private final IPointable argLen = new VoidPointable();
+    private final IEvaluatorContext ctx;
     private final IScalarEvaluator evalString;
     private final IScalarEvaluator evalStart;
     private final IScalarEvaluator evalLen;
@@ -55,11 +57,12 @@ class SubstringEval extends AbstractScalarEval {
     private final GrowableArray array = new GrowableArray();
     private final UTF8StringBuilder builder = new UTF8StringBuilder();
     private final UTF8StringPointable string = new UTF8StringPointable();
+    private final AMutableInt32 mutableInt32 = new AMutableInt32(0);
 
     SubstringEval(IEvaluatorContext ctx, IScalarEvaluatorFactory[] args, FunctionIdentifier functionIdentifier,
             SourceLocation sourceLoc, int baseOffset) throws HyracksDataException {
         super(sourceLoc, functionIdentifier);
-
+        this.ctx = ctx;
         evalString = args[0].createScalarEvaluator(ctx);
         evalStart = args[1].createScalarEvaluator(ctx);
         evalLen = args[2].createScalarEvaluator(ctx);
@@ -80,18 +83,27 @@ class SubstringEval extends AbstractScalarEval {
 
         byte[] bytes = argStart.getByteArray();
         int offset = argStart.getStartOffset();
-        int start = ATypeHierarchy.getIntegerValue(functionIdentifier.getName(), 0, bytes, offset);
+        if (!ArgumentUtils.checkWarnOrSetInteger(ctx, sourceLoc, functionIdentifier, 1, bytes, offset, mutableInt32)) {
+            PointableHelper.setNull(result);
+            return;
+        }
+        int start = mutableInt32.getIntegerValue();
 
         bytes = argLen.getByteArray();
         offset = argLen.getStartOffset();
-        int len = ATypeHierarchy.getIntegerValue(functionIdentifier.getName(), 1, bytes, offset);
+        if (!ArgumentUtils.checkWarnOrSetInteger(ctx, sourceLoc, functionIdentifier, 2, bytes, offset, mutableInt32)) {
+            PointableHelper.setNull(result);
+            return;
+        }
+        int len = mutableInt32.getIntegerValue();
 
         bytes = argString.getByteArray();
         offset = argString.getStartOffset();
         int length = argString.getLength();
         if (bytes[offset] != ATypeTag.SERIALIZED_STRING_TYPE_TAG) {
-            throw new TypeMismatchException(sourceLoc, functionIdentifier, 0, bytes[offset],
-                    ATypeTag.SERIALIZED_STRING_TYPE_TAG);
+            PointableHelper.setNull(result);
+            ExceptionUtil.warnTypeMismatch(ctx, sourceLoc, functionIdentifier, bytes[offset], 0, ATypeTag.STRING);
+            return;
         }
         string.set(bytes, offset + 1, length - 1);
         array.reset();
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/binary/BinaryConcatDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/binary/BinaryConcatDescriptor.java
index 4c6af01..907b591 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/binary/BinaryConcatDescriptor.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/binary/BinaryConcatDescriptor.java
@@ -103,6 +103,7 @@ public class BinaryConcatDescriptor extends AbstractScalarFunctionDynamicDescrip
                             int concatLength = 0;
                             boolean itemIsNull = false;
                             for (int i = 0; i < listAccessor.size(); i++) {
+                                // TODO(ali): itemOffset should be adjusted if list is heterogeneous like string_concat
                                 int itemOffset = listAccessor.getItemOffset(i);
                                 ATypeTag itemType = listAccessor.getItemType(itemOffset);
                                 if (itemType != ATypeTag.BINARY) {