[ASTERIXDB-2343][FUN] Implement to_array(), to_atomic(), to_object()

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

Details:
- Implement to_array(), to_atomic(), to_object() functions
- Add function aliases: to_bool, to_str

Change-Id: I6391a060ecd86cd397dd0a59f4930c4c55216d3b
Reviewed-on: https://asterix-gerrit.ics.uci.edu/2539
Reviewed-by: Till Westmann <tillw@apache.org>
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Contrib: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/ConstantFoldingRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/ConstantFoldingRule.java
index 7e9328b..29a8e77 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/ConstantFoldingRule.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/ConstantFoldingRule.java
@@ -92,7 +92,8 @@
             BuiltinFunctions.GET_RECORD_FIELDS, BuiltinFunctions.GET_RECORD_FIELD_VALUE,
             BuiltinFunctions.FIELD_ACCESS_NESTED, BuiltinFunctions.GET_ITEM, BuiltinFunctions.OPEN_RECORD_CONSTRUCTOR,
             BuiltinFunctions.FIELD_ACCESS_BY_INDEX, BuiltinFunctions.CAST_TYPE, BuiltinFunctions.META,
-            BuiltinFunctions.META_KEY, BuiltinFunctions.RECORD_CONCAT, BuiltinFunctions.RECORD_CONCAT_STRICT);
+            BuiltinFunctions.META_KEY, BuiltinFunctions.RECORD_CONCAT, BuiltinFunctions.RECORD_CONCAT_STRICT,
+            BuiltinFunctions.TO_ATOMIC, BuiltinFunctions.TO_ARRAY);
 
     /**
      * Throws exceptions in substituiteProducedVariable, setVarType, and one getVarType method.
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/to_array/to_array.1.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/to_array/to_array.1.query.sqlpp
new file mode 100644
index 0000000..c0814b5
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/to_array/to_array.1.query.sqlpp
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+{
+  "t1": [ toarray(missing) is missing, toarray(null) is null, is_array(to_array([])) ],
+  "t2": to_array([]),
+  "t3": to_array([1]),
+  "t4": to_array([1,2]),
+  "t5": to_array("hello"),
+  "t6": to_array({"a":1}),
+  "t7": to_array({{ 2 }}),
+  "t8": (
+    from range(1,4) t
+    select value to_array(t)
+    order by t
+  )
+}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/to_atomic/to_atomic.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/to_atomic/to_atomic.1.ddl.sqlpp
new file mode 100644
index 0000000..c156646
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/to_atomic/to_atomic.1.ddl.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.
+ */
+
+drop  dataverse test if exists;
+create  dataverse test;
+
+use test;
+
+create type test.T1 as
+{
+  id : bigint
+};
+
+create dataset t1(T1) primary key id;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/to_atomic/to_atomic.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/to_atomic/to_atomic.2.update.sqlpp
new file mode 100644
index 0000000..2397ffb
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/to_atomic/to_atomic.2.update.sqlpp
@@ -0,0 +1,32 @@
+/*
+ * 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 t1 select value t
+from [
+  { "id": 1, "v": 2 },
+  { "id": 2, "v": "hello" },
+  { "id": 3, "v": [[[2]]] },
+  { "id": 4, "v": [[[2, 3]]] },
+  { "id": 5, "v": {"a": 2} },
+  { "id": 6, "v": {"a": 2, "b": 3} },
+  { "id": 7, "v": {"a":{"b":{"c":{"d":2}}}} },
+  { "id": 8, "v": {"a":[{"b":[{"c":[2]}]}]} }
+] t
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/to_atomic/to_atomic.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/to_atomic/to_atomic.3.query.sqlpp
new file mode 100644
index 0000000..07303d9
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/to_atomic/to_atomic.3.query.sqlpp
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+{
+    "t1": [ toatomic(missing) is missing, toatom(null) is null ],
+    "t2": [ to_atomic(1), to_atomic(true), to_atomic("hello") ],
+    "t3": [ to_atomic([]), to_atomic([2]), to_atomic([2,3]), to_atomic([[[[4]]]]) ],
+    "t4": [ to_atomic({{}}), to_atomic({{2}}), to_atomic({{2,3}}), to_atomic({{{{{{{{4}}}}}}}}) ],
+    "t5": [ to_atomic({}), to_atomic({"a":2}), to_atomic({"a":2, "b":3}), to_atomic({"a":{"b":{"c":{"d":4}}}}) ],
+    "t6": [ to_atomic([{"a":1}]), to_atomic([{"a":1, "b":2}]), to_atomic({"a":[{"b":[{"c":[2]}]}]}) ],
+    "t7": (
+      from range(1,4) t
+      select to_atomic(t) v1, to_atomic([t]) v2, to_atomic({"a": t}) v3, to_atomic([[{"a":[t]}]]) v4
+      order by t
+    )
+}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/to_atomic/to_atomic.4.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/to_atomic/to_atomic.4.query.sqlpp
new file mode 100644
index 0000000..95fb2cb
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/to_atomic/to_atomic.4.query.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;
+
+select value [t.id, to_atomic(t.v) ]
+from t1 t
+order by t.id
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/to_object/to_object.1.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/to_object/to_object.1.query.sqlpp
new file mode 100644
index 0000000..e7c04f7
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/to_object/to_object.1.query.sqlpp
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+{
+  "t1": [ toobject(missing) is missing, toobj(null) is null ],
+  "t2": is_object(to_object({})),
+  "t3": to_object({}),
+  "t4": to_object({"a":1}),
+  "t5": to_object({"a":1, "b":2}),
+  "t6": (
+    from [
+      int8("1"), int16("2"), int32("3"), int64("4"), float("5"), double("6"),
+      "hello", [7], [ { "a": 1 } ]
+    ] t
+    select value to_object(t)
+  )
+}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/to_string_01/to_string_01.1.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/to_string_01/to_string_01.1.query.sqlpp
index f759e16..52a39fc 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/to_string_01/to_string_01.1.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/to_string_01/to_string_01.1.query.sqlpp
@@ -18,7 +18,7 @@
  */
  {
   "t1": tostring(false),
-  "t2": to_string(true),
+  "t2": tostr(true),
   "t3": to_string(int8("8")),
   "t4": to_string(int16("16")),
   "t5": to_string(int32("32")),
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/types/to_array/to_array.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/types/to_array/to_array.1.adm
new file mode 100644
index 0000000..5aeb739
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/types/to_array/to_array.1.adm
@@ -0,0 +1 @@
+{ "t1": [ true, true, true ], "t2": [  ], "t3": [ 1 ], "t4": [ 1, 2 ], "t5": [ "hello" ], "t6": [ { "a": 1 } ], "t7": [ 2 ], "t8": [ [ 1 ], [ 2 ], [ 3 ], [ 4 ] ] }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/types/to_atomic/to_atomic.3.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/types/to_atomic/to_atomic.3.adm
new file mode 100644
index 0000000..aec2ce7
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/types/to_atomic/to_atomic.3.adm
@@ -0,0 +1 @@
+{ "t1": [ true, true ], "t2": [ 1, true, "hello" ], "t3": [ null, 2, null, 4 ], "t4": [ null, 2, null, 4 ], "t5": [ null, 2, null, 4 ], "t6": [ 1, null, 2 ], "t7": [ { "v1": 1, "v2": 1, "v3": 1, "v4": 1 }, { "v1": 2, "v2": 2, "v3": 2, "v4": 2 }, { "v1": 3, "v2": 3, "v3": 3, "v4": 3 }, { "v1": 4, "v2": 4, "v3": 4, "v4": 4 } ] }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/types/to_atomic/to_atomic.4.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/types/to_atomic/to_atomic.4.adm
new file mode 100644
index 0000000..3f4c517
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/types/to_atomic/to_atomic.4.adm
@@ -0,0 +1,8 @@
+[ 1, 2 ]
+[ 2, "hello" ]
+[ 3, 2 ]
+[ 4, null ]
+[ 5, 2 ]
+[ 6, null ]
+[ 7, 2 ]
+[ 8, 2 ]
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/types/to_object/to_object.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/types/to_object/to_object.1.adm
new file mode 100644
index 0000000..ceb84c2
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/types/to_object/to_object.1.adm
@@ -0,0 +1 @@
+{ "t1": [ true, true ], "t2": true, "t3": {  }, "t4": { "a": 1 }, "t5": { "a": 1, "b": 2 }, "t6": [ {  }, {  }, {  }, {  }, {  }, {  }, {  }, {  }, {  } ] }
\ 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 dd2b626..1b49358 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
@@ -9229,6 +9229,16 @@
       </compilation-unit>
     </test-case>
     <test-case FilePath="types">
+      <compilation-unit name="to_array">
+        <output-dir compare="Text">to_array</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="types">
+      <compilation-unit name="to_atomic">
+        <output-dir compare="Text">to_atomic</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="types">
       <compilation-unit name="to_boolean_01">
         <output-dir compare="Text">to_boolean_01</output-dir>
       </compilation-unit>
@@ -9240,28 +9250,6 @@
       </compilation-unit>
     </test-case>
     <test-case FilePath="types">
-      <compilation-unit name="to_string_01">
-        <output-dir compare="Text">to_string_01</output-dir>
-      </compilation-unit>
-    </test-case>
-    <test-case FilePath="types">
-      <compilation-unit name="to_string_02">
-        <output-dir compare="Text">to_string_02</output-dir>
-        <expected-error>ASX0004: Unsupported type</expected-error>
-      </compilation-unit>
-    </test-case>
-    <test-case FilePath="types">
-      <compilation-unit name="to_double_01">
-        <output-dir compare="Text">to_double_01</output-dir>
-      </compilation-unit>
-    </test-case>
-    <test-case FilePath="types">
-      <compilation-unit name="to_double_02">
-        <output-dir compare="Text">to_double_02</output-dir>
-        <expected-error>ASX0002: Type mismatch</expected-error>
-      </compilation-unit>
-    </test-case>
-    <test-case FilePath="types">
       <compilation-unit name="to_bigint_01">
         <output-dir compare="Text">to_bigint_01</output-dir>
       </compilation-unit>
@@ -9273,6 +9261,17 @@
       </compilation-unit>
     </test-case>
     <test-case FilePath="types">
+      <compilation-unit name="to_double_01">
+        <output-dir compare="Text">to_double_01</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="types">
+      <compilation-unit name="to_double_02">
+        <output-dir compare="Text">to_double_02</output-dir>
+        <expected-error>ASX0002: Type mismatch</expected-error>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="types">
       <compilation-unit name="to_number_01">
         <output-dir compare="Text">to_number_01</output-dir>
       </compilation-unit>
@@ -9283,6 +9282,22 @@
         <expected-error>ASX0002: Type mismatch</expected-error>
       </compilation-unit>
     </test-case>
+    <test-case FilePath="types">
+      <compilation-unit name="to_object">
+        <output-dir compare="Text">to_object</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="types">
+      <compilation-unit name="to_string_01">
+        <output-dir compare="Text">to_string_01</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="types">
+      <compilation-unit name="to_string_02">
+        <output-dir compare="Text">to_string_02</output-dir>
+        <expected-error>ASX0004: Unsupported type</expected-error>
+      </compilation-unit>
+    </test-case>
   </test-group>
   <test-group name="materialization">
     <test-case FilePath="materialization">
diff --git a/asterixdb/asterix-doc/src/main/markdown/builtins/11_type.md b/asterixdb/asterix-doc/src/main/markdown/builtins/11_type.md
index f972735..578508f 100644
--- a/asterixdb/asterix-doc/src/main/markdown/builtins/11_type.md
+++ b/asterixdb/asterix-doc/src/main/markdown/builtins/11_type.md
@@ -293,6 +293,67 @@
 
  The function has an alias `isunknown`.
 
+### to_array ###
+  * Syntax:
+
+        to_array(expr)
+
+  * Converts input value to an `array` value
+  * Arguments:
+     * `expr` : an expression
+  * Return Value:
+     * if the argument is `missing` then `missing` is returned
+     * if the argument is `null` then `null` is returned
+     * if the argument is of `array` type then it is returned as is
+     * if the argument is of `multiset` type then it is returned as an `array` with elements in an undefined order
+     * otherwise an `array` containing the input expression as its single item is returned
+
+ * Example:
+
+        {
+          "v1": to_array("asterix"),
+          "v2": to_array(["asterix"]),
+        };
+
+ * The expected result is:
+
+        { "v1": ["asterix"], "v2": ["asterix"] }
+
+ The function has an alias `toarray`.
+
+### to_atomic ###
+  * Syntax:
+
+        to_atomic(expr)
+
+  * Converts input value to a [primitive](../datamodel.html#PrimitiveTypes) value
+  * Arguments:
+     * `expr` : an expression
+  * Return Value:
+     * if the argument is `missing` then `missing` is returned
+     * if the argument is `null` then `null` is returned
+     * if the argument is of primitive type then it is returned as is
+     * if the argument is of `array` or `multiset` type and has only one element then the result of invoking
+       to_atomic() on that element is returned
+     * if the argument is of `object` type and has only one field then the result of invoking to_atomic() on the
+       value of that field is returned
+     * otherwise `null` is returned
+
+ * Example:
+
+        {
+          "v1": to_atomic("asterix"),
+          "v2": to_atomic(["asterix"]),
+          "v3": to_atomic([0, 1]),
+          "v4": to_atomic({"value": "asterix"}),
+          "v5": to_number({"x": 1, "y": 2})
+        };
+
+ * The expected result is:
+
+        { "v1": "asterix", "v2": "asterix", "v3": null, "v4": "asterix", "v5": null }
+
+ The function has two aliases, `toatomic` or `toatom`.
 
 ### to_boolean ###
   * Syntax:
@@ -325,8 +386,7 @@
 
         { "v1": false, "v2": true, "v3": false, "v4": true }
 
- The function has an alias `toboolean`.
-
+ The function has two aliases, `toboolean` or `tobool`.
 
 ### to_bigint ###
   * Syntax:
@@ -364,7 +424,6 @@
 
  The function has an alias `tobigint`.
 
-
 ### to_double ###
   * Syntax:
 
@@ -432,7 +491,34 @@
 
         { "v1": 0, "v2": 1, "v3": 10, "v4": 11.5, "v5": 12.5 }
 
- The function has an alias `tonumber`.
+ The function has two aliases, `tonumber` or `tonum`.
+
+### to_object ###
+  * Syntax:
+
+        to_object(expr)
+
+  * Converts input value to an `object` value
+  * Arguments:
+     * `expr` : an expression
+  * Return Value:
+     * if the argument is `missing` then `missing` is returned
+     * if the argument is `null` then `null` is returned
+     * if the argument is of `object` type then it is returned as is
+     * otherwise an empty `object` is returned
+
+ * Example:
+
+        {
+          "v1": to_object({"value": "asterix"}),
+          "v2": to_object("asterix")
+        };
+
+ * The expected result is:
+
+        { "v1": {"value": "asterix"}, "v2": {} }
+
+ The function has two aliases, `toobject` or `toobj`.
 
 ### to_string ###
   * Syntax:
@@ -465,4 +551,4 @@
 
         { "v1": "false", "v2": "true", "v3": "10", "v4": "11.5", "v5": "asterix" }
 
- The function has an alias `tostring`.
+ The function has two aliases, `tostring` or `tostr`.
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/CommonFunctionMapUtil.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/CommonFunctionMapUtil.java
index 3116521..3dffc00 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/CommonFunctionMapUtil.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/CommonFunctionMapUtil.java
@@ -69,12 +69,19 @@
         addFunctionMapping("ifinf", "if-inf"); // ifinf, internal: if-inf
         addFunctionMapping("ifnan", "if-nan"); // ifnan, internal: if-nan
         addFunctionMapping("ifnanorinf", "if-nan-or-inf"); // ifnanorinf, internal: if-nan-or-inf
+        addFunctionMapping("toarray", "to-array"); // toarray, internal: to-array
+        addFunctionMapping("toatomic", "to-atomic"); // toatomic, internal: to-atomic
+        addFunctionMapping("toatom", "to-atomic"); // toatom, internal: to-atomic
         addFunctionMapping("toboolean", "to-boolean"); // toboolean, internal: to-boolean
-        addFunctionMapping("tostring", "to-string"); // tostring, internal: to-string
-        addFunctionMapping("todouble", "to-double"); // todouble, internal: to-double
+        addFunctionMapping("tobool", "to-boolean"); // tobool, internal: to-boolean
         addFunctionMapping("tobigint", "to-bigint"); // tobigint, internal: to-bigint
+        addFunctionMapping("todouble", "to-double"); // todouble, internal: to-double
+        addFunctionMapping("tostring", "to-string"); // tostring, internal: to-string
+        addFunctionMapping("tostr", "to-string"); // tostr, internal: to-string
         addFunctionMapping("tonumber", "to-number"); // tonumber, internal: to-number
         addFunctionMapping("tonum", "to-number"); // tonum, internal: to-number
+        addFunctionMapping("toobject", "to-object"); // toobject, internal: to-object
+        addFunctionMapping("toobj", "to-object"); // toobj, internal: to-object
 
         // Object functions
         // record-merge, internal: object-merge
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 6b86a26..8cd18fc 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,9 +106,11 @@
 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;
 import org.apache.asterix.om.typecomputer.impl.ToDoubleTypeComputer;
 import org.apache.asterix.om.typecomputer.impl.ToNumberTypeComputer;
+import org.apache.asterix.om.typecomputer.impl.ToObjectTypeComputer;
 import org.apache.asterix.om.typecomputer.impl.UnaryBinaryInt64TypeComputer;
 import org.apache.asterix.om.typecomputer.impl.UnaryMinusTypeComputer;
 import org.apache.asterix.om.typecomputer.impl.UnaryStringInt64TypeComputer;
@@ -874,16 +876,22 @@
     public static final FunctionIdentifier IF_NAN_OR_INF =
             new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "if-nan-or-inf", FunctionIdentifier.VARARGS);
 
-    public static final FunctionIdentifier TO_BOOLEAN =
-            new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "to-boolean", 1);
-    public static final FunctionIdentifier TO_STRING =
-            new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "to-string", 1);
-    public static final FunctionIdentifier TO_DOUBLE =
-            new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "to-double", 1);
+    public static final FunctionIdentifier TO_ATOMIC =
+            new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "to-atomic", 1);
+    public static final FunctionIdentifier TO_ARRAY =
+            new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "to-array", 1);
     public static final FunctionIdentifier TO_BIGINT =
             new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "to-bigint", 1);
+    public static final FunctionIdentifier TO_BOOLEAN =
+            new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "to-boolean", 1);
+    public static final FunctionIdentifier TO_DOUBLE =
+            new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "to-double", 1);
     public static final FunctionIdentifier TO_NUMBER =
             new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "to-number", 1);
+    public static final FunctionIdentifier TO_OBJECT =
+            new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "to-object", 1);
+    public static final FunctionIdentifier TO_STRING =
+            new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "to-string", 1);
 
     public static final FunctionIdentifier EXTERNAL_LOOKUP =
             new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "external-lookup", FunctionIdentifier.VARARGS);
@@ -1070,11 +1078,14 @@
         addFunction(RANGE, AInt64TypeComputer.INSTANCE, true);
         addFunction(RECTANGLE_CONSTRUCTOR, ARectangleTypeComputer.INSTANCE, true);
 
-        addFunction(TO_BOOLEAN, ABooleanTypeComputer.INSTANCE, true);
-        addFunction(TO_STRING, AStringTypeComputer.INSTANCE, true);
-        addFunction(TO_DOUBLE, ToDoubleTypeComputer.INSTANCE, true);
+        addFunction(TO_ATOMIC, AnyTypeComputer.INSTANCE, true);
+        addFunction(TO_ARRAY, ToArrayTypeComputer.INSTANCE, true);
         addFunction(TO_BIGINT, ToBigIntTypeComputer.INSTANCE, true);
+        addFunction(TO_BOOLEAN, ABooleanTypeComputer.INSTANCE, true);
+        addFunction(TO_DOUBLE, ToDoubleTypeComputer.INSTANCE, true);
         addFunction(TO_NUMBER, ToNumberTypeComputer.INSTANCE, true);
+        addFunction(TO_OBJECT, ToObjectTypeComputer.INSTANCE, true);
+        addFunction(TO_STRING, AStringTypeComputer.INSTANCE, true);
 
         // Aggregate Functions
         addFunction(MAX, MinMaxAggTypeComputer.INSTANCE, true);
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/ToArrayTypeComputer.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/ToArrayTypeComputer.java
new file mode 100644
index 0000000..e33284f
--- /dev/null
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/ToArrayTypeComputer.java
@@ -0,0 +1,47 @@
+/*
+ * 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.typecomputer.base.AbstractResultTypeComputer;
+import org.apache.asterix.om.types.AOrderedListType;
+import org.apache.asterix.om.types.AUnorderedListType;
+import org.apache.asterix.om.types.IAType;
+import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
+import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
+
+public class ToArrayTypeComputer extends AbstractResultTypeComputer {
+    public static final ToArrayTypeComputer INSTANCE = new ToArrayTypeComputer();
+
+    private ToArrayTypeComputer() {
+    }
+
+    @Override
+    protected IAType getResultType(ILogicalExpression expr, IAType... strippedInputTypes) throws AlgebricksException {
+        IAType argType = strippedInputTypes[0];
+        switch (argType.getTypeTag()) {
+            case ARRAY:
+                return argType;
+            case MULTISET:
+                return new AOrderedListType(((AUnorderedListType) argType).getItemType(), null);
+            default:
+                return new AOrderedListType(argType, null);
+        }
+    }
+}
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/ToObjectTypeComputer.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/ToObjectTypeComputer.java
new file mode 100644
index 0000000..116f7ac
--- /dev/null
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/ToObjectTypeComputer.java
@@ -0,0 +1,41 @@
+/*
+ * 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.typecomputer.base.AbstractResultTypeComputer;
+import org.apache.asterix.om.types.ATypeTag;
+import org.apache.asterix.om.types.IAType;
+import org.apache.asterix.om.utils.RecordUtil;
+import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
+import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
+
+public class ToObjectTypeComputer extends AbstractResultTypeComputer {
+    public static final ToObjectTypeComputer INSTANCE = new ToObjectTypeComputer();
+
+    private ToObjectTypeComputer() {
+    }
+
+    @Override
+    protected IAType getResultType(ILogicalExpression expr, IAType... strippedInputTypes) throws AlgebricksException {
+        IAType strippedInputType = strippedInputTypes[0];
+        return strippedInputType.getTypeTag() == ATypeTag.OBJECT ? strippedInputType
+                : RecordUtil.FULLY_OPEN_RECORD_TYPE;
+    }
+}
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ToArrayDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ToArrayDescriptor.java
new file mode 100644
index 0000000..9764aed
--- /dev/null
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ToArrayDescriptor.java
@@ -0,0 +1,117 @@
+/*
+ * 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 java.io.DataOutput;
+import java.io.IOException;
+
+import org.apache.asterix.builders.OrderedListBuilder;
+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.functions.IFunctionTypeInferer;
+import org.apache.asterix.om.typecomputer.impl.TypeComputeUtils;
+import org.apache.asterix.om.types.AOrderedListType;
+import org.apache.asterix.om.types.ATypeTag;
+import org.apache.asterix.om.types.IAType;
+import org.apache.asterix.runtime.evaluators.base.AbstractScalarFunctionDynamicDescriptor;
+import org.apache.asterix.runtime.functions.FunctionTypeInferers;
+import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory;
+import org.apache.hyracks.api.context.IHyracksTaskContext;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+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;
+
+public class ToArrayDescriptor extends AbstractScalarFunctionDynamicDescriptor {
+    public static final IFunctionDescriptorFactory FACTORY = new IFunctionDescriptorFactory() {
+        @Override
+        public IFunctionDescriptor createFunctionDescriptor() {
+            return new ToArrayDescriptor();
+        }
+
+        @Override
+        public IFunctionTypeInferer createFunctionTypeInferer() {
+            return FunctionTypeInferers.SET_EXPRESSION_TYPE;
+        }
+    };
+
+    private static final long serialVersionUID = 1L;
+    private AOrderedListType oltype;
+
+    @Override
+    public void setImmutableStates(Object... states) {
+        oltype = TypeComputeUtils.extractOrderedListType((IAType) states[0]);
+    }
+
+    @Override
+    public IScalarEvaluatorFactory createEvaluatorFactory(final IScalarEvaluatorFactory[] args) {
+        return new IScalarEvaluatorFactory() {
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            public IScalarEvaluator createScalarEvaluator(final IHyracksTaskContext ctx) throws HyracksDataException {
+
+                return new IScalarEvaluator() {
+
+                    private final IScalarEvaluator eval0 = args[0].createScalarEvaluator(ctx);
+                    private final IPointable arg0 = new VoidPointable();
+                    private final OrderedListBuilder listBuilder = new OrderedListBuilder();
+                    private final ArrayBackedValueStorage resultStorage = new ArrayBackedValueStorage();
+                    private final DataOutput out = resultStorage.getDataOutput();
+
+                    @Override
+                    public void evaluate(IFrameTupleReference tuple, IPointable resultPointable)
+                            throws HyracksDataException {
+                        eval0.evaluate(tuple, arg0);
+                        byte[] data = arg0.getByteArray();
+                        int offset = arg0.getStartOffset();
+                        if (data[offset] == ATypeTag.SERIALIZED_ORDEREDLIST_TYPE_TAG) {
+                            resultPointable.set(arg0);
+                        } else if (data[offset] == ATypeTag.SERIALIZED_UNORDEREDLIST_TYPE_TAG) {
+                            try {
+                                resultStorage.reset();
+                                out.writeByte(ATypeTag.SERIALIZED_ORDEREDLIST_TYPE_TAG);
+                                out.write(data, offset + 1, arg0.getLength() - 1);
+                                resultPointable.set(resultStorage);
+                            } catch (IOException e) {
+                                throw HyracksDataException.create(e);
+                            }
+                        } else {
+                            resultStorage.reset();
+                            listBuilder.reset(oltype);
+                            listBuilder.addItem(arg0);
+                            listBuilder.write(out, true);
+                            resultPointable.set(resultStorage);
+                        }
+                    }
+                };
+            }
+        };
+    }
+
+    @Override
+    public FunctionIdentifier getIdentifier() {
+        return BuiltinFunctions.TO_ARRAY;
+    }
+}
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ToAtomicDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ToAtomicDescriptor.java
new file mode 100644
index 0000000..16554b5
--- /dev/null
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ToAtomicDescriptor.java
@@ -0,0 +1,194 @@
+/*
+ * 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 java.util.List;
+
+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.functions.IFunctionTypeInferer;
+import org.apache.asterix.om.pointables.AListVisitablePointable;
+import org.apache.asterix.om.pointables.ARecordVisitablePointable;
+import org.apache.asterix.om.pointables.PointableAllocator;
+import org.apache.asterix.om.pointables.base.DefaultOpenFieldType;
+import org.apache.asterix.om.pointables.base.IVisitablePointable;
+import org.apache.asterix.om.types.AOrderedListType;
+import org.apache.asterix.om.types.ARecordType;
+import org.apache.asterix.om.types.ATypeTag;
+import org.apache.asterix.om.types.AUnionType;
+import org.apache.asterix.om.types.AUnorderedListType;
+import org.apache.asterix.om.types.BuiltinType;
+import org.apache.asterix.om.types.IAType;
+import org.apache.asterix.runtime.evaluators.base.AbstractScalarFunctionDynamicDescriptor;
+import org.apache.asterix.runtime.functions.FunctionTypeInferers;
+import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory;
+import org.apache.hyracks.api.context.IHyracksTaskContext;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.apache.hyracks.data.std.api.IPointable;
+import org.apache.hyracks.data.std.api.IValueReference;
+import org.apache.hyracks.data.std.primitive.VoidPointable;
+import org.apache.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
+
+public class ToAtomicDescriptor extends AbstractScalarFunctionDynamicDescriptor {
+    public static final IFunctionDescriptorFactory FACTORY = new IFunctionDescriptorFactory() {
+        @Override
+        public IFunctionDescriptor createFunctionDescriptor() {
+            return new ToAtomicDescriptor();
+        }
+
+        @Override
+        public IFunctionTypeInferer createFunctionTypeInferer() {
+            return FunctionTypeInferers.SET_ARGUMENT_TYPE;
+        }
+    };
+
+    private static final long serialVersionUID = 1L;
+    private IAType argType;
+
+    @Override
+    public void setImmutableStates(Object... states) {
+        argType = (IAType) states[0];
+    }
+
+    @Override
+    public IScalarEvaluatorFactory createEvaluatorFactory(final IScalarEvaluatorFactory[] args) {
+        return new IScalarEvaluatorFactory() {
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            public IScalarEvaluator createScalarEvaluator(final IHyracksTaskContext ctx) throws HyracksDataException {
+
+                return new IScalarEvaluator() {
+
+                    private final IScalarEvaluator eval0 = args[0].createScalarEvaluator(ctx);
+                    private final IPointable arg = new VoidPointable();
+
+                    private final PointableAllocator pAlloc = new PointableAllocator();
+
+                    @Override
+                    public void evaluate(IFrameTupleReference tuple, IPointable resultPointable)
+                            throws HyracksDataException {
+                        eval0.evaluate(tuple, arg);
+
+                        IValueReference itemPtr = arg;
+                        IAType itemTypeInferred = argType;
+
+                        for (;;) {
+                            byte[] itemData = itemPtr.getByteArray();
+                            int itemOffset = itemPtr.getStartOffset();
+                            ATypeTag typeTag = ATypeTag.VALUE_TYPE_MAPPING[itemData[itemOffset]];
+                            switch (typeTag) {
+                                case ARRAY:
+                                case MULTISET:
+                                    AListVisitablePointable listPointable =
+                                            (AListVisitablePointable) allocatePointable(itemTypeInferred, typeTag);
+                                    listPointable.set(itemPtr);
+                                    List<IVisitablePointable> listItems = listPointable.getItems();
+                                    if (listItems.size() != 1) {
+                                        PointableHelper.setNull(resultPointable);
+                                        return;
+                                    }
+                                    itemPtr = listItems.get(0);
+                                    itemTypeInferred = getListItemType(itemTypeInferred);
+                                    break;
+                                case OBJECT:
+                                    ARecordType recType = asRecordType(itemTypeInferred);
+                                    ARecordVisitablePointable recPointable =
+                                            (ARecordVisitablePointable) allocatePointable(itemTypeInferred, typeTag);
+                                    recPointable.set(itemPtr);
+                                    List<IVisitablePointable> recValues = recPointable.getFieldValues();
+                                    if (recValues.size() != 1) {
+                                        PointableHelper.setNull(resultPointable);
+                                        return;
+                                    }
+                                    itemPtr = recValues.get(0);
+                                    itemTypeInferred = recType.getFieldTypes().length == 1 ? recType.getFieldTypes()[0]
+                                            : BuiltinType.ANY;
+                                    break;
+                                default:
+                                    resultPointable.set(itemPtr);
+                                    return;
+                            }
+                        }
+                    }
+
+                    private IVisitablePointable allocatePointable(IAType inferredType, ATypeTag actualTypeTag) {
+                        if (inferredType.equals(BuiltinType.ANY)) {
+                            return allocatePointableForAny(actualTypeTag);
+                        }
+                        return pAlloc.allocateFieldValue(inferredType);
+                    }
+
+                    private IVisitablePointable allocatePointableForAny(ATypeTag typeTag) {
+                        switch (typeTag) {
+                            case OBJECT:
+                                return pAlloc.allocateFieldValue(DefaultOpenFieldType.NESTED_OPEN_RECORD_TYPE);
+                            case ARRAY:
+                                return pAlloc.allocateFieldValue(DefaultOpenFieldType.NESTED_OPEN_AORDERED_LIST_TYPE);
+                            case MULTISET:
+                                return pAlloc.allocateFieldValue(DefaultOpenFieldType.NESTED_OPEN_AUNORDERED_LIST_TYPE);
+                            default:
+                                return pAlloc.allocateFieldValue(null);
+                        }
+                    }
+
+                    private ARecordType asRecordType(IAType inferredType) {
+                        switch (inferredType.getTypeTag()) {
+                            case OBJECT:
+                                return (ARecordType) inferredType;
+                            case UNION:
+                                IAType innerType = ((AUnionType) inferredType).getActualType();
+                                if (innerType.getTypeTag() == ATypeTag.OBJECT) {
+                                    return (ARecordType) innerType;
+                                }
+                        }
+                        return DefaultOpenFieldType.NESTED_OPEN_RECORD_TYPE;
+                    }
+
+                    private IAType getListItemType(IAType inferredType) {
+                        switch (inferredType.getTypeTag()) {
+                            case ARRAY:
+                                return ((AOrderedListType) inferredType).getItemType();
+                            case MULTISET:
+                                return ((AUnorderedListType) inferredType).getItemType();
+                            case UNION:
+                                IAType innerType = ((AUnionType) inferredType).getActualType();
+                                switch (innerType.getTypeTag()) {
+                                    case ARRAY:
+                                        return ((AOrderedListType) innerType).getItemType();
+                                    case MULTISET:
+                                        return ((AUnorderedListType) innerType).getItemType();
+                                }
+                        }
+                        return BuiltinType.ANY;
+                    }
+                };
+            }
+        };
+    }
+
+    @Override
+    public FunctionIdentifier getIdentifier() {
+        return BuiltinFunctions.TO_ATOMIC;
+    }
+}
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ToObjectDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ToObjectDescriptor.java
new file mode 100644
index 0000000..82dbd95
--- /dev/null
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ToObjectDescriptor.java
@@ -0,0 +1,97 @@
+/*
+ * 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 java.io.DataOutput;
+
+import org.apache.asterix.builders.RecordBuilder;
+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.runtime.evaluators.base.AbstractScalarFunctionDynamicDescriptor;
+import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory;
+import org.apache.hyracks.api.context.IHyracksTaskContext;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+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;
+
+public class ToObjectDescriptor extends AbstractScalarFunctionDynamicDescriptor {
+    public static final IFunctionDescriptorFactory FACTORY = new IFunctionDescriptorFactory() {
+        @Override
+        public IFunctionDescriptor createFunctionDescriptor() {
+            return new ToObjectDescriptor();
+        }
+    };
+
+    @Override
+    public IScalarEvaluatorFactory createEvaluatorFactory(final IScalarEvaluatorFactory[] args) {
+        return new IScalarEvaluatorFactory() {
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            public IScalarEvaluator createScalarEvaluator(final IHyracksTaskContext ctx) throws HyracksDataException {
+
+                return new IScalarEvaluator() {
+
+                    private final IScalarEvaluator eval0 = args[0].createScalarEvaluator(ctx);
+                    private final IPointable arg0 = new VoidPointable();
+                    private final RecordBuilder recordBuilder = new RecordBuilder();
+                    private final ArrayBackedValueStorage resultStorage = new ArrayBackedValueStorage();
+                    private final DataOutput out = resultStorage.getDataOutput();
+                    private boolean wroteEmpty;
+
+                    @Override
+                    public void evaluate(IFrameTupleReference tuple, IPointable resultPointable)
+                            throws HyracksDataException {
+                        eval0.evaluate(tuple, arg0);
+                        byte[] data = arg0.getByteArray();
+                        int offset = arg0.getStartOffset();
+                        if (data[offset] == ATypeTag.SERIALIZED_RECORD_TYPE_TAG) {
+                            resultPointable.set(arg0);
+                        } else {
+                            writeEmpty();
+                            resultPointable.set(resultStorage);
+                        }
+                    }
+
+                    private void writeEmpty() throws HyracksDataException {
+                        if (!wroteEmpty) {
+                            resultStorage.reset();
+                            recordBuilder.reset(null);
+                            recordBuilder.init();
+                            recordBuilder.write(out, true);
+                            wroteEmpty = true;
+                        }
+                    }
+                };
+            }
+        };
+    }
+
+    @Override
+    public FunctionIdentifier getIdentifier() {
+        return BuiltinFunctions.TO_OBJECT;
+    }
+}
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/functions/FunctionCollection.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/functions/FunctionCollection.java
index 6648ff2..b05dbed 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/functions/FunctionCollection.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/functions/FunctionCollection.java
@@ -241,10 +241,13 @@
 import org.apache.asterix.runtime.evaluators.functions.SubstringBeforeDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.SubstringDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.SwitchCaseDescriptor;
+import org.apache.asterix.runtime.evaluators.functions.ToArrayDescriptor;
+import org.apache.asterix.runtime.evaluators.functions.ToAtomicDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.ToBigIntDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.ToBooleanDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.ToDoubleDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.ToNumberDescriptor;
+import org.apache.asterix.runtime.evaluators.functions.ToObjectDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.ToStringDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.UUIDDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.binary.BinaryConcatDescriptor;
@@ -689,17 +692,20 @@
         fc.addGenerated(DurationFromIntervalDescriptor.FACTORY);
 
         // Type functions.
+        fc.addGenerated(IsArrayDescriptor.FACTORY);
         fc.addGenerated(IsAtomicDescriptor.FACTORY);
         fc.addGenerated(IsBooleanDescriptor.FACTORY);
         fc.addGenerated(IsNumberDescriptor.FACTORY);
-        fc.addGenerated(IsStringDescriptor.FACTORY);
-        fc.addGenerated(IsArrayDescriptor.FACTORY);
         fc.addGenerated(IsObjectDescriptor.FACTORY);
-        fc.addGenerated(ToBooleanDescriptor.FACTORY);
-        fc.addGenerated(ToStringDescriptor.FACTORY);
-        fc.addGenerated(ToDoubleDescriptor.FACTORY);
+        fc.addGenerated(IsStringDescriptor.FACTORY);
+        fc.addGenerated(ToArrayDescriptor.FACTORY);
+        fc.addGenerated(ToAtomicDescriptor.FACTORY);
         fc.addGenerated(ToBigIntDescriptor.FACTORY);
+        fc.addGenerated(ToBooleanDescriptor.FACTORY);
+        fc.addGenerated(ToDoubleDescriptor.FACTORY);
         fc.addGenerated(ToNumberDescriptor.FACTORY);
+        fc.addGenerated(ToObjectDescriptor.FACTORY);
+        fc.addGenerated(ToStringDescriptor.FACTORY);
 
         // Cast function
         fc.addGenerated(CastTypeDescriptor.FACTORY);
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/functions/FunctionTypeInferers.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/functions/FunctionTypeInferers.java
index be041e5..e5a4301 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/functions/FunctionTypeInferers.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/functions/FunctionTypeInferers.java
@@ -69,6 +69,16 @@
         }
     };
 
+    public static final IFunctionTypeInferer SET_ARGUMENT_TYPE = new IFunctionTypeInferer() {
+        @Override
+        public void infer(ILogicalExpression expr, IFunctionDescriptor fd, IVariableTypeEnvironment context,
+                CompilerProperties compilerProps) throws AlgebricksException {
+            AbstractFunctionCallExpression fce = (AbstractFunctionCallExpression) expr;
+            IAType t = (IAType) context.getType(fce.getArguments().get(0).getValue());
+            fd.setImmutableStates(TypeComputeUtils.getActualType(t));
+        }
+    };
+
     public static final class CastTypeInferer implements IFunctionTypeInferer {
         @Override
         public void infer(ILogicalExpression expr, IFunctionDescriptor fd, IVariableTypeEnvironment context,