You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@asterixdb.apache.org by dl...@apache.org on 2018/03/05 20:10:00 UTC

asterixdb git commit: [NO ISSUE][FUN] Add to_number() function

Repository: asterixdb
Updated Branches:
  refs/heads/master 63f29624d -> 17ad87595


[NO ISSUE][FUN] Add to_number() function

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

Details:
- add to_number() function
- add testcases and documentation
- fix type inference for to_bigint() and to_double()
  to return optional type in cases when NULL can
  be produced at runtime

Change-Id: Id370aadcf16447f7c775c30d2bffc33fc6a96927
Reviewed-on: https://asterix-gerrit.ics.uci.edu/2449
Tested-by: Jenkins <je...@fulliautomatix.ics.uci.edu>
Integration-Tests: Jenkins <je...@fulliautomatix.ics.uci.edu>
Contrib: Jenkins <je...@fulliautomatix.ics.uci.edu>
Reviewed-by: Till Westmann <ti...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/asterixdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/asterixdb/commit/17ad8759
Tree: http://git-wip-us.apache.org/repos/asf/asterixdb/tree/17ad8759
Diff: http://git-wip-us.apache.org/repos/asf/asterixdb/diff/17ad8759

Branch: refs/heads/master
Commit: 17ad87595391b818063d2b8eaaa63ffb957e9f8c
Parents: 63f2962
Author: Dmitry Lychagin <dm...@couchbase.com>
Authored: Sun Mar 4 09:59:12 2018 -0800
Committer: Dmitry Lychagin <dm...@couchbase.com>
Committed: Mon Mar 5 12:09:45 2018 -0800

----------------------------------------------------------------------
 .../to_number_01/to_number_01.1.query.sqlpp     |  42 ++++++
 .../to_number_02/to_number_02.1.query.sqlpp     |  21 +++
 .../types/to_number_01/to_number_01.1.adm       |   1 +
 .../resources/runtimets/testsuite_sqlpp.xml     |  11 ++
 .../src/main/markdown/builtins/11_type.md       |  34 +++++
 .../lang/common/util/CommonFunctionMapUtil.java |   2 +
 .../asterix/om/functions/BuiltinFunctions.java  |  10 +-
 .../typecomputer/impl/ToBigIntTypeComputer.java |  53 +++++++
 .../typecomputer/impl/ToDoubleTypeComputer.java |  53 +++++++
 .../typecomputer/impl/ToNumberTypeComputer.java |  52 +++++++
 .../org/apache/asterix/om/types/AUnionType.java |   8 +
 .../runtime/evaluators/common/NumberUtils.java  | 119 +++++++++++++++
 .../AFloatConstructorDescriptor.java            |  13 +-
 .../AbstractDoubleConstructorEvaluator.java     |  39 ++---
 .../AbstractInt64ConstructorEvaluator.java      |  47 +-----
 .../AbstractStringConstructorEvaluator.java     |  13 +-
 .../functions/ToBigIntDescriptor.java           |  19 +--
 .../functions/ToBooleanDescriptor.java          |  10 +-
 .../functions/ToDoubleDescriptor.java           |  20 +--
 .../functions/ToNumberDescriptor.java           | 149 +++++++++++++++++++
 .../runtime/functions/FunctionCollection.java   |   2 +
 21 files changed, 591 insertions(+), 127 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/asterixdb/blob/17ad8759/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/to_number_01/to_number_01.1.query.sqlpp
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/to_number_01/to_number_01.1.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/to_number_01/to_number_01.1.query.sqlpp
new file mode 100644
index 0000000..739a6a9
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/to_number_01/to_number_01.1.query.sqlpp
@@ -0,0 +1,42 @@
+/*
+ * 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": tonumber(false),
+  "t2": to_number(true),
+  "t3": tonum(int8("8")),
+  "t4": to_number(int16("16")),
+  "t5": to_number(int32("32")),
+  "t6": to_number(int64("64")),
+  "t7": to_number(float("1.5")),
+  "t8": to_number(double("2.25")),
+  "t9": to_number("512"),
+  "t10": is_null(to_number("foo")),
+  "t11": is_null(to_number([])),
+  "t12": is_null(to_number({{}})),
+  "t13": is_null(to_number({})),
+  "t14": is_null(to_number(null)),
+  "t15": is_missing(to_number(missing)),
+  "t16": to_string(to_number(float("INF"))),
+  "t17": to_string(to_number(float("-INF"))),
+  "t18": to_string(to_number(float("NaN"))),
+  "t19": to_string(to_number(double("INF"))),
+  "t20": to_string(to_number(double("-INF"))),
+  "t21": to_string(to_number(double("NaN")))
+ };

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/17ad8759/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/to_number_02/to_number_02.1.query.sqlpp
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/to_number_02/to_number_02.1.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/to_number_02/to_number_02.1.query.sqlpp
new file mode 100644
index 0000000..837750e
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/to_number_02/to_number_02.1.query.sqlpp
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+{
+ "t": to_number(date("2017-06-30"))
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/17ad8759/asterixdb/asterix-app/src/test/resources/runtimets/results/types/to_number_01/to_number_01.1.adm
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/types/to_number_01/to_number_01.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/types/to_number_01/to_number_01.1.adm
new file mode 100644
index 0000000..72416e4
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/types/to_number_01/to_number_01.1.adm
@@ -0,0 +1 @@
+{ "t1": 0, "t2": 1, "t3": 8, "t4": 16, "t5": 32, "t6": 64, "t7": 1.5, "t8": 2.25, "t9": 512, "t10": true, "t11": true, "t12": true, "t13": true, "t14": true, "t15": true, "t16": "INF", "t17": "-INF", "t18": "NaN", "t19": "INF", "t20": "-INF", "t21": "NaN" }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/17ad8759/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
----------------------------------------------------------------------
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 67980d0..6bb1886 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
@@ -9285,6 +9285,17 @@
         <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>
+    </test-case>
+    <test-case FilePath="types">
+      <compilation-unit name="to_number_02">
+        <output-dir compare="Text">to_number_02</output-dir>
+        <expected-error>ASX0002: Type mismatch</expected-error>
+      </compilation-unit>
+    </test-case>
   </test-group>
   <test-group name="materialization">
     <test-case FilePath="materialization">

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/17ad8759/asterixdb/asterix-doc/src/main/markdown/builtins/11_type.md
----------------------------------------------------------------------
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 fd6a262..f972735 100644
--- a/asterixdb/asterix-doc/src/main/markdown/builtins/11_type.md
+++ b/asterixdb/asterix-doc/src/main/markdown/builtins/11_type.md
@@ -399,6 +399,40 @@
 
  The function has an alias `todouble`.
 
+### to_number ###
+  * Syntax:
+
+        to_number(expr)
+
+  * Converts input value to a numeric 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 numeric type then it is returned as is
+     * if the argument is of `boolean` type then `1` is returned if it is `true`, `0` if it is `false`
+     * if the argument is of `string` type and can be parsed as `bigint` then that `bigint` value is returned,
+       otherwise if it can be parsed as `double` then that `double` value is returned,
+       otherwise `null` is returned
+     * if the argument is of `array`/`multiset`/`object` type then `null` is returned
+     * type error is raised for all other input types
+
+ * Example:
+
+        {
+          "v1": to_number(false),
+          "v2": to_number(true),
+          "v3": to_number(10),
+          "v4": to_number(11.5),
+          "v5": to_number("12.5")
+        };
+
+ * The expected result is:
+
+        { "v1": 0, "v2": 1, "v3": 10, "v4": 11.5, "v5": 12.5 }
+
+ The function has an alias `tonumber`.
 
 ### to_string ###
   * Syntax:

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/17ad8759/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/CommonFunctionMapUtil.java
----------------------------------------------------------------------
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 e5d1643..0646224 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
@@ -74,6 +74,8 @@ public class CommonFunctionMapUtil {
         FUNCTION_NAME_MAP.put("tostring", "to-string"); // tostring, internal: to-string
         FUNCTION_NAME_MAP.put("todouble", "to-double"); // todouble, internal: to-double
         FUNCTION_NAME_MAP.put("tobigint", "to-bigint"); // tobigint, internal: to-bigint
+        FUNCTION_NAME_MAP.put("tonumber", "to-number"); // tonumber, internal: to-number
+        FUNCTION_NAME_MAP.put("tonum", "to-number"); // tonum, internal: to-number
 
         // Object functions
         // record-merge, internal: object-merge

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/17ad8759/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/BuiltinFunctions.java
----------------------------------------------------------------------
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 761ddba..3e3cf43 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,6 +106,9 @@ import org.apache.asterix.om.typecomputer.impl.StringToStringListTypeComputer;
 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.ToBigIntTypeComputer;
+import org.apache.asterix.om.typecomputer.impl.ToDoubleTypeComputer;
+import org.apache.asterix.om.typecomputer.impl.ToNumberTypeComputer;
 import org.apache.asterix.om.typecomputer.impl.UnaryBinaryInt64TypeComputer;
 import org.apache.asterix.om.typecomputer.impl.UnaryMinusTypeComputer;
 import org.apache.asterix.om.typecomputer.impl.UnaryStringInt64TypeComputer;
@@ -871,6 +874,8 @@ public class BuiltinFunctions {
             new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "to-double", 1);
     public static final FunctionIdentifier TO_BIGINT =
             new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "to-bigint", 1);
+    public static final FunctionIdentifier TO_NUMBER =
+            new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "to-number", 1);
 
     public static final FunctionIdentifier EXTERNAL_LOOKUP =
             new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "external-lookup", FunctionIdentifier.VARARGS);
@@ -1057,8 +1062,9 @@ public class BuiltinFunctions {
 
         addFunction(TO_BOOLEAN, ABooleanTypeComputer.INSTANCE, true);
         addFunction(TO_STRING, AStringTypeComputer.INSTANCE, true);
-        addFunction(TO_DOUBLE, ADoubleTypeComputer.INSTANCE, true);
-        addFunction(TO_BIGINT, AInt64TypeComputer.INSTANCE, true);
+        addFunction(TO_DOUBLE, ToDoubleTypeComputer.INSTANCE, true);
+        addFunction(TO_BIGINT, ToBigIntTypeComputer.INSTANCE, true);
+        addFunction(TO_NUMBER, ToNumberTypeComputer.INSTANCE, true);
 
         // Aggregate Functions
         addFunction(MAX, MinMaxAggTypeComputer.INSTANCE, true);

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/17ad8759/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/ToBigIntTypeComputer.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/ToBigIntTypeComputer.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/ToBigIntTypeComputer.java
new file mode 100644
index 0000000..e7b6f42
--- /dev/null
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/ToBigIntTypeComputer.java
@@ -0,0 +1,53 @@
+/*
+ * 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.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;
+
+public class ToBigIntTypeComputer extends AbstractResultTypeComputer {
+
+    public static final ToBigIntTypeComputer INSTANCE = new ToBigIntTypeComputer();
+
+    private ToBigIntTypeComputer() {
+    }
+
+    @Override
+    protected IAType getResultType(ILogicalExpression expr, IAType... strippedInputTypes) throws AlgebricksException {
+        IAType strippedInputType = strippedInputTypes[0];
+        switch (strippedInputType.getTypeTag()) {
+            case BOOLEAN:
+            case TINYINT:
+            case SMALLINT:
+            case INTEGER:
+            case BIGINT:
+            case FLOAT:
+            case DOUBLE:
+                // these types cannot result in NULL output
+                return BuiltinType.AINT64;
+            default:
+                return AUnionType.createNullableType(BuiltinType.AINT64);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/17ad8759/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/ToDoubleTypeComputer.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/ToDoubleTypeComputer.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/ToDoubleTypeComputer.java
new file mode 100644
index 0000000..7794aab
--- /dev/null
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/ToDoubleTypeComputer.java
@@ -0,0 +1,53 @@
+/*
+ * 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.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;
+
+public class ToDoubleTypeComputer extends AbstractResultTypeComputer {
+
+    public static final ToDoubleTypeComputer INSTANCE = new ToDoubleTypeComputer();
+
+    private ToDoubleTypeComputer() {
+    }
+
+    @Override
+    protected IAType getResultType(ILogicalExpression expr, IAType... strippedInputTypes) throws AlgebricksException {
+        IAType strippedInputType = strippedInputTypes[0];
+        switch (strippedInputType.getTypeTag()) {
+            case BOOLEAN:
+            case TINYINT:
+            case SMALLINT:
+            case INTEGER:
+            case BIGINT:
+            case FLOAT:
+            case DOUBLE:
+                // these types cannot result in NULL output
+                return BuiltinType.ADOUBLE;
+            default:
+                return AUnionType.createNullableType(BuiltinType.ADOUBLE);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/17ad8759/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/ToNumberTypeComputer.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/ToNumberTypeComputer.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/ToNumberTypeComputer.java
new file mode 100644
index 0000000..077a1eb
--- /dev/null
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/ToNumberTypeComputer.java
@@ -0,0 +1,52 @@
+/*
+ * 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.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;
+
+public class ToNumberTypeComputer extends AbstractResultTypeComputer {
+    public static final ToNumberTypeComputer INSTANCE = new ToNumberTypeComputer();
+
+    private ToNumberTypeComputer() {
+    }
+
+    @Override
+    protected IAType getResultType(ILogicalExpression expr, IAType... strippedInputTypes) throws AlgebricksException {
+        IAType strippedInputType = strippedInputTypes[0];
+        switch (strippedInputType.getTypeTag()) {
+            case BOOLEAN:
+                return BuiltinType.AINT64;
+            case TINYINT:
+            case SMALLINT:
+            case INTEGER:
+            case BIGINT:
+            case FLOAT:
+            case DOUBLE:
+                return strippedInputType;
+            default:
+                // STRING can be parsed as either BIGINT or DOUBLE
+                return BuiltinType.ANY;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/17ad8759/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/AUnionType.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/AUnionType.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/AUnionType.java
index 007f072..9fdaca1 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/AUnionType.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/AUnionType.java
@@ -99,6 +99,14 @@ public class AUnionType extends AbstractComplexType {
         return createMissableType(t, s == null ? null : s + "?");
     }
 
+    public static IAType createNullableType(IAType t) {
+        if (t != null && t.getTypeTag() == ATypeTag.NULL) {
+            return t;
+        }
+        String s = t != null ? t.getTypeName() : null;
+        return createNullableType(t, s == null ? null : s + "?");
+    }
+
     public static IAType createNullableType(IAType type, String typeName) {
         if (type != null && type.getTypeTag() == ATypeTag.NULL) {
             return type;

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/17ad8759/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/common/NumberUtils.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/common/NumberUtils.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/common/NumberUtils.java
new file mode 100644
index 0000000..0b2e94c
--- /dev/null
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/common/NumberUtils.java
@@ -0,0 +1,119 @@
+/*
+ * 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.common;
+
+import org.apache.asterix.om.base.AMutableDouble;
+import org.apache.asterix.om.base.AMutableInt64;
+import org.apache.hyracks.data.std.primitive.UTF8StringPointable;
+
+/**
+ * Utility methods for number handling
+ */
+public final class NumberUtils {
+
+    public static final UTF8StringPointable POSITIVE_INF = UTF8StringPointable.generateUTF8Pointable("INF");
+
+    public static final UTF8StringPointable NEGATIVE_INF = UTF8StringPointable.generateUTF8Pointable("-INF");
+
+    public static final UTF8StringPointable NAN = UTF8StringPointable.generateUTF8Pointable("NaN");
+
+    public static final long NAN_BITS = Double.doubleToLongBits(Double.NaN);
+
+    public static final long POSITIVE_ZERO_BITS = Double.doubleToLongBits(+0.0d);
+
+    public static final long NEGATIVE_ZERO_BITS = Double.doubleToLongBits(-0.0d);
+
+    /**
+     * Parses string as double
+     * @param textPtr input string
+     * @param result placeholder for the result
+     * @return {@code true} if parsing was successful, {@code false} otherwise
+     */
+    public static boolean parseDouble(UTF8StringPointable textPtr, AMutableDouble result) {
+        double v;
+        if (POSITIVE_INF.compareTo(textPtr) == 0) {
+            v = Double.POSITIVE_INFINITY;
+        } else if (NEGATIVE_INF.compareTo(textPtr) == 0) {
+            v = Double.NEGATIVE_INFINITY;
+        } else if (NAN.compareTo(textPtr) == 0) {
+            v = Double.NaN;
+        } else {
+            try {
+                v = Double.parseDouble(textPtr.toString());
+            } catch (NumberFormatException e) {
+                return false;
+            }
+        }
+        result.setValue(v);
+        return true;
+    }
+
+    /**
+     * Parses string as bigint
+     * @param textPtr input string
+     * @param result placeholder for the result
+     * @return {@code true} if parsing was successful, {@code false} otherwise
+     */
+    public static boolean parseInt64(UTF8StringPointable textPtr, AMutableInt64 result) {
+        byte[] bytes = textPtr.getByteArray();
+        int offset = textPtr.getCharStartOffset();
+        //accumulating value in negative domain
+        //otherwise Long.MIN_VALUE = -(Long.MAX_VALUE + 1) would have caused overflow
+        long value = 0;
+        boolean positive = true;
+        long limit = -Long.MAX_VALUE;
+        if (bytes[offset] == '+') {
+            offset++;
+        } else if (bytes[offset] == '-') {
+            offset++;
+            positive = false;
+            limit = Long.MIN_VALUE;
+        }
+        int end = textPtr.getStartOffset() + textPtr.getLength();
+        for (; offset < end; offset++) {
+            int digit;
+            if (bytes[offset] >= '0' && bytes[offset] <= '9') {
+                value *= 10;
+                digit = bytes[offset] - '0';
+            } else if (bytes[offset] == 'i' && bytes[offset + 1] == '6' && bytes[offset + 2] == '4'
+                    && offset + 3 == end) {
+                break;
+            } else {
+                return false;
+            }
+            if (value < limit + digit) {
+                return false;
+            }
+            value -= digit;
+        }
+        if (value > 0) {
+            return false;
+        }
+        if (value < 0 && positive) {
+            value *= -1;
+        }
+
+        result.setValue(value);
+        return true;
+    }
+
+    private NumberUtils() {
+    }
+}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/17ad8759/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/constructors/AFloatConstructorDescriptor.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/constructors/AFloatConstructorDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/constructors/AFloatConstructorDescriptor.java
index 8c69671..b6f045e 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/constructors/AFloatConstructorDescriptor.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/constructors/AFloatConstructorDescriptor.java
@@ -21,7 +21,6 @@ package org.apache.asterix.runtime.evaluators.constructors;
 import java.io.DataOutput;
 import java.io.IOException;
 
-import org.apache.asterix.formats.nontagged.BinaryComparatorFactoryProvider;
 import org.apache.asterix.formats.nontagged.SerializerDeserializerProvider;
 import org.apache.asterix.om.base.AFloat;
 import org.apache.asterix.om.base.AMutableFloat;
@@ -31,13 +30,13 @@ 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.NumberUtils;
 import org.apache.asterix.runtime.exceptions.InvalidDataFormatException;
 import org.apache.asterix.runtime.exceptions.TypeMismatchException;
 import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
 import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
 import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory;
 import org.apache.hyracks.api.context.IHyracksTaskContext;
-import org.apache.hyracks.api.dataflow.value.IBinaryComparator;
 import org.apache.hyracks.api.dataflow.value.ISerializerDeserializer;
 import org.apache.hyracks.api.exceptions.HyracksDataException;
 import org.apache.hyracks.data.std.api.IPointable;
@@ -45,7 +44,6 @@ import org.apache.hyracks.data.std.primitive.UTF8StringPointable;
 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;
-import org.apache.hyracks.util.string.UTF8StringUtil;
 
 public class AFloatConstructorDescriptor extends AbstractScalarFunctionDynamicDescriptor {
     private static final long serialVersionUID = 1L;
@@ -89,14 +87,11 @@ public class AFloatConstructorDescriptor extends AbstractScalarFunctionDynamicDe
                                 resultStorage.reset();
                                 int utf8offset = offset + 1;
                                 int utf8len = len - 1;
-                                if (AbstractDoubleConstructorEvaluator.POSITIVE_INF.compareTo(serString, utf8offset,
-                                        utf8len) == 0) {
+                                if (NumberUtils.POSITIVE_INF.compareTo(serString, utf8offset, utf8len) == 0) {
                                     aFloat.setValue(Float.POSITIVE_INFINITY);
-                                } else if (AbstractDoubleConstructorEvaluator.NEGATIVE_INF.compareTo(serString,
-                                        utf8offset, utf8len) == 0) {
+                                } else if (NumberUtils.NEGATIVE_INF.compareTo(serString, utf8offset, utf8len) == 0) {
                                     aFloat.setValue(Float.NEGATIVE_INFINITY);
-                                } else if (AbstractDoubleConstructorEvaluator.NAN.compareTo(serString, utf8offset,
-                                        utf8len) == 0) {
+                                } else if (NumberUtils.NAN.compareTo(serString, utf8offset, utf8len) == 0) {
                                     aFloat.setValue(Float.NaN);
                                 } else {
                                     utf8Ptr.set(serString, utf8offset, utf8len);

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/17ad8759/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/constructors/AbstractDoubleConstructorEvaluator.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/constructors/AbstractDoubleConstructorEvaluator.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/constructors/AbstractDoubleConstructorEvaluator.java
index e10bf68..456735f 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/constructors/AbstractDoubleConstructorEvaluator.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/constructors/AbstractDoubleConstructorEvaluator.java
@@ -27,6 +27,7 @@ import org.apache.asterix.om.base.ADouble;
 import org.apache.asterix.om.base.AMutableDouble;
 import org.apache.asterix.om.types.ATypeTag;
 import org.apache.asterix.om.types.BuiltinType;
+import org.apache.asterix.runtime.evaluators.common.NumberUtils;
 import org.apache.asterix.runtime.exceptions.InvalidDataFormatException;
 import org.apache.asterix.runtime.exceptions.TypeMismatchException;
 import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
@@ -44,10 +45,6 @@ public abstract class AbstractDoubleConstructorEvaluator implements IScalarEvalu
     protected static final ISerializerDeserializer<ADouble> DOUBLE_SERDE =
             SerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.ADOUBLE);
 
-    protected static final UTF8StringPointable POSITIVE_INF = UTF8StringPointable.generateUTF8Pointable("INF");
-    protected static final UTF8StringPointable NEGATIVE_INF = UTF8StringPointable.generateUTF8Pointable("-INF");
-    protected static final UTF8StringPointable NAN = UTF8StringPointable.generateUTF8Pointable("NaN");
-
     protected final IScalarEvaluator inputEval;
     protected final ArrayBackedValueStorage resultStorage;
     protected final DataOutput out;
@@ -77,41 +74,25 @@ public abstract class AbstractDoubleConstructorEvaluator implements IScalarEvalu
 
     protected void evaluateImpl(IPointable result) throws IOException {
         byte[] bytes = inputArg.getByteArray();
-        int offset = inputArg.getStartOffset();
-        byte tt = bytes[offset];
+        int startOffset = inputArg.getStartOffset();
+        byte tt = bytes[startOffset];
         if (tt == ATypeTag.SERIALIZED_DOUBLE_TYPE_TAG) {
             result.set(inputArg);
         } else if (tt == ATypeTag.SERIALIZED_STRING_TYPE_TAG) {
-            int len = inputArg.getLength();
-            int utf8offset = offset + 1;
-            int utf8len = len - 1;
-            if (POSITIVE_INF.compareTo(bytes, utf8offset, utf8len) == 0) {
-                setDouble(result, Double.POSITIVE_INFINITY);
-            } else if (NEGATIVE_INF.compareTo(bytes, utf8offset, utf8len) == 0) {
-                setDouble(result, Double.NEGATIVE_INFINITY);
-            } else if (NAN.compareTo(bytes, utf8offset, utf8len) == 0) {
-                setDouble(result, Double.NaN);
+            utf8Ptr.set(bytes, startOffset + 1, inputArg.getLength() - 1);
+            if (NumberUtils.parseDouble(utf8Ptr, aDouble)) {
+                DOUBLE_SERDE.serialize(aDouble, out);
+                result.set(resultStorage);
             } else {
-                utf8Ptr.set(bytes, utf8offset, utf8len);
-                try {
-                    setDouble(result, Double.parseDouble(utf8Ptr.toString()));
-                } catch (NumberFormatException e) {
-                    handleUparseableString(result, e);
-                }
+                handleUparseableString(result);
             }
         } else {
             throw new TypeMismatchException(getIdentifier(), 0, tt, ATypeTag.SERIALIZED_STRING_TYPE_TAG);
         }
     }
 
-    protected void handleUparseableString(IPointable result, NumberFormatException e) throws HyracksDataException {
-        throw new InvalidDataFormatException(getIdentifier(), e, ATypeTag.SERIALIZED_DOUBLE_TYPE_TAG);
-    }
-
-    protected void setDouble(IPointable result, double value) throws HyracksDataException {
-        aDouble.setValue(value);
-        DOUBLE_SERDE.serialize(aDouble, out);
-        result.set(resultStorage);
+    protected void handleUparseableString(IPointable result) throws HyracksDataException {
+        throw new InvalidDataFormatException(getIdentifier(), ATypeTag.SERIALIZED_DOUBLE_TYPE_TAG);
     }
 
     protected abstract FunctionIdentifier getIdentifier();

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/17ad8759/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/constructors/AbstractInt64ConstructorEvaluator.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/constructors/AbstractInt64ConstructorEvaluator.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/constructors/AbstractInt64ConstructorEvaluator.java
index 8cf9bed..2f9470d 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/constructors/AbstractInt64ConstructorEvaluator.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/constructors/AbstractInt64ConstructorEvaluator.java
@@ -27,6 +27,7 @@ import org.apache.asterix.om.base.AInt64;
 import org.apache.asterix.om.base.AMutableInt64;
 import org.apache.asterix.om.types.ATypeTag;
 import org.apache.asterix.om.types.BuiltinType;
+import org.apache.asterix.runtime.evaluators.common.NumberUtils;
 import org.apache.asterix.runtime.exceptions.InvalidDataFormatException;
 import org.apache.asterix.runtime.exceptions.TypeMismatchException;
 import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
@@ -79,49 +80,13 @@ public abstract class AbstractInt64ConstructorEvaluator implements IScalarEvalua
         if (tt == ATypeTag.SERIALIZED_INT64_TYPE_TAG) {
             result.set(inputArg);
         } else if (tt == ATypeTag.SERIALIZED_STRING_TYPE_TAG) {
-            int len = inputArg.getLength();
-            utf8Ptr.set(bytes, startOffset + 1, len - 1);
-            int offset = utf8Ptr.getCharStartOffset();
-            //accumulating value in negative domain
-            //otherwise Long.MIN_VALUE = -(Long.MAX_VALUE + 1) would have caused overflow
-            long value = 0;
-            boolean positive = true;
-            long limit = -Long.MAX_VALUE;
-            if (bytes[offset] == '+') {
-                offset++;
-            } else if (bytes[offset] == '-') {
-                offset++;
-                positive = false;
-                limit = Long.MIN_VALUE;
-            }
-            int end = startOffset + len;
-            for (; offset < end; offset++) {
-                int digit;
-                if (bytes[offset] >= '0' && bytes[offset] <= '9') {
-                    value *= 10;
-                    digit = bytes[offset] - '0';
-                } else if (bytes[offset] == 'i' && bytes[offset + 1] == '6' && bytes[offset + 2] == '4'
-                        && offset + 3 == end) {
-                    break;
-                } else {
-                    handleUnparseableString(result);
-                    return;
-                }
-                if (value < limit + digit) {
-                    handleUnparseableString(result);
-                }
-                value -= digit;
-            }
-            if (value > 0) {
+            utf8Ptr.set(bytes, startOffset + 1, inputArg.getLength() - 1);
+            if (NumberUtils.parseInt64(utf8Ptr, aInt64)) {
+                INT64_SERDE.serialize(aInt64, out);
+                result.set(resultStorage);
+            } else {
                 handleUnparseableString(result);
             }
-            if (value < 0 && positive) {
-                value *= -1;
-            }
-
-            aInt64.setValue(value);
-            INT64_SERDE.serialize(aInt64, out);
-            result.set(resultStorage);
         } else {
             throw new TypeMismatchException(getIdentifier(), 0, tt, ATypeTag.SERIALIZED_STRING_TYPE_TAG);
         }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/17ad8759/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/constructors/AbstractStringConstructorEvaluator.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/constructors/AbstractStringConstructorEvaluator.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/constructors/AbstractStringConstructorEvaluator.java
index 11576aa..52d3bf6 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/constructors/AbstractStringConstructorEvaluator.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/constructors/AbstractStringConstructorEvaluator.java
@@ -30,6 +30,7 @@ import org.apache.asterix.dataflow.data.nontagged.serde.AInt32SerializerDeserial
 import org.apache.asterix.dataflow.data.nontagged.serde.AInt64SerializerDeserializer;
 import org.apache.asterix.dataflow.data.nontagged.serde.AInt8SerializerDeserializer;
 import org.apache.asterix.om.types.ATypeTag;
+import org.apache.asterix.runtime.evaluators.common.NumberUtils;
 import org.apache.asterix.runtime.exceptions.InvalidDataFormatException;
 import org.apache.asterix.runtime.exceptions.UnsupportedTypeException;
 import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
@@ -107,11 +108,11 @@ public abstract class AbstractStringConstructorEvaluator implements IScalarEvalu
                 case DOUBLE: {
                     double d = ADoubleSerializerDeserializer.getDouble(serString, startOffset);
                     if (Double.isNaN(d)) {
-                        builder.appendUtf8StringPointable(AbstractDoubleConstructorEvaluator.NAN);
+                        builder.appendUtf8StringPointable(NumberUtils.NAN);
                     } else if (d == Double.POSITIVE_INFINITY) { // NOSONAR
-                        builder.appendUtf8StringPointable(AbstractDoubleConstructorEvaluator.POSITIVE_INF);
+                        builder.appendUtf8StringPointable(NumberUtils.POSITIVE_INF);
                     } else if (d == Double.NEGATIVE_INFINITY) { // NOSONAR
-                        builder.appendUtf8StringPointable(AbstractDoubleConstructorEvaluator.NEGATIVE_INF);
+                        builder.appendUtf8StringPointable(NumberUtils.NEGATIVE_INF);
                     } else {
                         builder.appendString(String.valueOf(d));
                     }
@@ -120,11 +121,11 @@ public abstract class AbstractStringConstructorEvaluator implements IScalarEvalu
                 case FLOAT: {
                     float f = AFloatSerializerDeserializer.getFloat(serString, startOffset);
                     if (Float.isNaN(f)) {
-                        builder.appendUtf8StringPointable(AbstractDoubleConstructorEvaluator.NAN);
+                        builder.appendUtf8StringPointable(NumberUtils.NAN);
                     } else if (f == Float.POSITIVE_INFINITY) { // NOSONAR
-                        builder.appendUtf8StringPointable(AbstractDoubleConstructorEvaluator.POSITIVE_INF);
+                        builder.appendUtf8StringPointable(NumberUtils.POSITIVE_INF);
                     } else if (f == Float.NEGATIVE_INFINITY) { // NOSONAR
-                        builder.appendUtf8StringPointable(AbstractDoubleConstructorEvaluator.NEGATIVE_INF);
+                        builder.appendUtf8StringPointable(NumberUtils.NEGATIVE_INF);
                     } else {
                         builder.appendString(String.valueOf(f));
                     }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/17ad8759/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ToBigIntDescriptor.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ToBigIntDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ToBigIntDescriptor.java
index 5cf9af7..2762d61 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ToBigIntDescriptor.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ToBigIntDescriptor.java
@@ -22,13 +22,10 @@ package org.apache.asterix.runtime.evaluators.functions;
 import java.io.IOException;
 
 import org.apache.asterix.dataflow.data.nontagged.serde.ABooleanSerializerDeserializer;
-import org.apache.asterix.formats.nontagged.SerializerDeserializerProvider;
-import org.apache.asterix.om.base.ANull;
 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.om.types.hierachy.ATypeHierarchy;
 import org.apache.asterix.om.types.hierachy.ITypeConvertComputer;
 import org.apache.asterix.runtime.evaluators.base.AbstractScalarFunctionDynamicDescriptor;
@@ -37,7 +34,6 @@ import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
 import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
 import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory;
 import org.apache.hyracks.api.context.IHyracksTaskContext;
-import org.apache.hyracks.api.dataflow.value.ISerializerDeserializer;
 import org.apache.hyracks.api.exceptions.HyracksDataException;
 import org.apache.hyracks.data.std.api.IPointable;
 
@@ -58,10 +54,6 @@ public class ToBigIntDescriptor extends AbstractScalarFunctionDynamicDescriptor
             @Override
             public IScalarEvaluator createScalarEvaluator(final IHyracksTaskContext ctx) throws HyracksDataException {
                 return new AbstractInt64ConstructorEvaluator(args[0].createScalarEvaluator(ctx)) {
-                    @SuppressWarnings("unchecked")
-                    private final ISerializerDeserializer<ANull> nullSerde =
-                            SerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.ANULL);
-
                     @Override
                     protected void evaluateImpl(IPointable result) throws IOException {
                         byte[] bytes = inputArg.getByteArray();
@@ -94,7 +86,7 @@ public class ToBigIntDescriptor extends AbstractScalarFunctionDynamicDescriptor
                             case ARRAY:
                             case MULTISET:
                             case OBJECT:
-                                setNull(result);
+                                PointableHelper.setNull(result);
                                 break;
 
                             default:
@@ -104,13 +96,8 @@ public class ToBigIntDescriptor extends AbstractScalarFunctionDynamicDescriptor
                     }
 
                     @Override
-                    protected void handleUnparseableString(IPointable result) throws HyracksDataException {
-                        setNull(result);
-                    }
-
-                    private void setNull(IPointable result) throws HyracksDataException {
-                        nullSerde.serialize(ANull.NULL, out);
-                        result.set(resultStorage);
+                    protected void handleUnparseableString(IPointable result) {
+                        PointableHelper.setNull(result);
                     }
 
                     @Override

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/17ad8759/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ToBooleanDescriptor.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ToBooleanDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ToBooleanDescriptor.java
index 704630e..fccd6d1 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ToBooleanDescriptor.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ToBooleanDescriptor.java
@@ -33,6 +33,7 @@ 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.asterix.runtime.evaluators.common.NumberUtils;
 import org.apache.asterix.runtime.evaluators.constructors.AbstractBooleanConstructorEvaluator;
 import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
 import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
@@ -45,12 +46,6 @@ import org.apache.hyracks.util.string.UTF8StringUtil;
 public class ToBooleanDescriptor extends AbstractScalarFunctionDynamicDescriptor {
     private static final long serialVersionUID = 1L;
 
-    private static final long BITS_NAN = Double.doubleToLongBits(Double.NaN);
-
-    private static final long BITS_ZERO_POS = Double.doubleToLongBits(+0.0d);
-
-    private static final long BITS_ZERO_NEG = Double.doubleToLongBits(-0.0d);
-
     public static final IFunctionDescriptorFactory FACTORY = new IFunctionDescriptorFactory() {
         @Override
         public IFunctionDescriptor createFunctionDescriptor() {
@@ -117,7 +112,8 @@ public class ToBooleanDescriptor extends AbstractScalarFunctionDynamicDescriptor
 
                     private void setDouble(double v, IPointable result) throws HyracksDataException {
                         long bits = Double.doubleToLongBits(v);
-                        boolean zeroOrNaN = bits == BITS_ZERO_POS || bits == BITS_ZERO_NEG || bits == BITS_NAN;
+                        boolean zeroOrNaN = bits == NumberUtils.POSITIVE_ZERO_BITS
+                                || bits == NumberUtils.NEGATIVE_ZERO_BITS || bits == NumberUtils.NAN_BITS;
                         setBoolean(result, !zeroOrNaN);
                     }
 

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/17ad8759/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ToDoubleDescriptor.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ToDoubleDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ToDoubleDescriptor.java
index 71cdbe5..4fa33de 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ToDoubleDescriptor.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ToDoubleDescriptor.java
@@ -22,13 +22,10 @@ package org.apache.asterix.runtime.evaluators.functions;
 import java.io.IOException;
 
 import org.apache.asterix.dataflow.data.nontagged.serde.ABooleanSerializerDeserializer;
-import org.apache.asterix.formats.nontagged.SerializerDeserializerProvider;
-import org.apache.asterix.om.base.ANull;
 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.om.types.hierachy.ATypeHierarchy;
 import org.apache.asterix.om.types.hierachy.ITypeConvertComputer;
 import org.apache.asterix.runtime.evaluators.base.AbstractScalarFunctionDynamicDescriptor;
@@ -37,7 +34,6 @@ import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
 import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
 import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory;
 import org.apache.hyracks.api.context.IHyracksTaskContext;
-import org.apache.hyracks.api.dataflow.value.ISerializerDeserializer;
 import org.apache.hyracks.api.exceptions.HyracksDataException;
 import org.apache.hyracks.data.std.api.IPointable;
 
@@ -58,10 +54,6 @@ public class ToDoubleDescriptor extends AbstractScalarFunctionDynamicDescriptor
             @Override
             public IScalarEvaluator createScalarEvaluator(final IHyracksTaskContext ctx) throws HyracksDataException {
                 return new AbstractDoubleConstructorEvaluator(args[0].createScalarEvaluator(ctx)) {
-                    @SuppressWarnings("unchecked")
-                    private final ISerializerDeserializer<ANull> nullSerde =
-                            SerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.ANULL);
-
                     @Override
                     protected void evaluateImpl(IPointable result) throws IOException {
                         byte[] bytes = inputArg.getByteArray();
@@ -88,7 +80,7 @@ public class ToDoubleDescriptor extends AbstractScalarFunctionDynamicDescriptor
                             case ARRAY:
                             case MULTISET:
                             case OBJECT:
-                                setNull(result);
+                                PointableHelper.setNull(result);
                                 break;
 
                             default:
@@ -98,14 +90,8 @@ public class ToDoubleDescriptor extends AbstractScalarFunctionDynamicDescriptor
                     }
 
                     @Override
-                    protected void handleUparseableString(IPointable result, NumberFormatException e)
-                            throws HyracksDataException {
-                        setNull(result);
-                    }
-
-                    private void setNull(IPointable result) throws HyracksDataException {
-                        nullSerde.serialize(ANull.NULL, out);
-                        result.set(resultStorage);
+                    protected void handleUparseableString(IPointable result) {
+                        PointableHelper.setNull(result);
                     }
 
                     @Override

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/17ad8759/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ToNumberDescriptor.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ToNumberDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ToNumberDescriptor.java
new file mode 100644
index 0000000..d044744
--- /dev/null
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ToNumberDescriptor.java
@@ -0,0 +1,149 @@
+/*
+ * 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.dataflow.data.nontagged.serde.ABooleanSerializerDeserializer;
+import org.apache.asterix.formats.nontagged.SerializerDeserializerProvider;
+import org.apache.asterix.om.base.ADouble;
+import org.apache.asterix.om.base.AInt64;
+import org.apache.asterix.om.base.AMutableDouble;
+import org.apache.asterix.om.base.AMutableInt64;
+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.NumberUtils;
+import org.apache.asterix.runtime.exceptions.TypeMismatchException;
+import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory;
+import org.apache.hyracks.api.context.IHyracksTaskContext;
+import org.apache.hyracks.api.dataflow.value.ISerializerDeserializer;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.apache.hyracks.data.std.api.IPointable;
+import org.apache.hyracks.data.std.primitive.UTF8StringPointable;
+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 ToNumberDescriptor extends AbstractScalarFunctionDynamicDescriptor {
+    private static final long serialVersionUID = 1L;
+    public static final IFunctionDescriptorFactory FACTORY = new IFunctionDescriptorFactory() {
+        @Override
+        public IFunctionDescriptor createFunctionDescriptor() {
+            return new ToNumberDescriptor();
+        }
+    };
+
+    @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 {
+
+                final IScalarEvaluator inputEval = args[0].createScalarEvaluator(ctx);
+                final IPointable inputArg = new VoidPointable();
+                final ArrayBackedValueStorage resultStorage = new ArrayBackedValueStorage();
+                final DataOutput out = resultStorage.getDataOutput();
+                final AMutableInt64 aInt64 = new AMutableInt64(0);
+                final AMutableDouble aDouble = new AMutableDouble(0);
+                final UTF8StringPointable utf8Ptr = new UTF8StringPointable();
+
+                @SuppressWarnings("unchecked")
+                final ISerializerDeserializer<AInt64> INT64_SERDE =
+                        SerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.AINT64);
+
+                @SuppressWarnings("unchecked")
+                final ISerializerDeserializer<ADouble> DOUBLE_SERDE =
+                        SerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.ADOUBLE);
+
+                return new IScalarEvaluator() {
+                    @Override
+                    public void evaluate(IFrameTupleReference tuple, IPointable result) throws HyracksDataException {
+                        inputEval.evaluate(tuple, inputArg);
+
+                        resultStorage.reset();
+
+                        byte[] bytes = inputArg.getByteArray();
+                        int startOffset = inputArg.getStartOffset();
+                        ATypeTag tt = ATypeTag.VALUE_TYPE_MAPPING[bytes[startOffset]];
+                        switch (tt) {
+                            case TINYINT:
+                            case SMALLINT:
+                            case INTEGER:
+                            case BIGINT:
+                            case FLOAT:
+                            case DOUBLE:
+                                result.set(inputArg);
+                                break;
+
+                            case BOOLEAN:
+                                boolean b = ABooleanSerializerDeserializer.getBoolean(bytes, startOffset + 1);
+                                aInt64.setValue(b ? 1 : 0);
+                                INT64_SERDE.serialize(aInt64, out);
+                                result.set(resultStorage);
+                                break;
+
+                            case STRING:
+                                utf8Ptr.set(bytes, startOffset + 1, inputArg.getLength() - 1);
+                                if (NumberUtils.parseInt64(utf8Ptr, aInt64)) {
+                                    INT64_SERDE.serialize(aInt64, out);
+                                    result.set(resultStorage);
+                                } else if (NumberUtils.parseDouble(utf8Ptr, aDouble)) {
+                                    DOUBLE_SERDE.serialize(aDouble, out);
+                                    result.set(resultStorage);
+                                } else {
+                                    PointableHelper.setNull(result);
+                                }
+                                break;
+
+                            case ARRAY:
+                            case MULTISET:
+                            case OBJECT:
+                                PointableHelper.setNull(result);
+                                break;
+
+                            default:
+                                throw new TypeMismatchException(getIdentifier(), 0, bytes[startOffset],
+                                        ATypeTag.SERIALIZED_INT8_TYPE_TAG, ATypeTag.SERIALIZED_INT16_TYPE_TAG,
+                                        ATypeTag.SERIALIZED_INT32_TYPE_TAG, ATypeTag.SERIALIZED_INT64_TYPE_TAG,
+                                        ATypeTag.SERIALIZED_FLOAT_TYPE_TAG, ATypeTag.SERIALIZED_DOUBLE_TYPE_TAG,
+                                        ATypeTag.SERIALIZED_BOOLEAN_TYPE_TAG, ATypeTag.SERIALIZED_STRING_TYPE_TAG,
+                                        ATypeTag.SERIALIZED_ORDEREDLIST_TYPE_TAG,
+                                        ATypeTag.SERIALIZED_UNORDEREDLIST_TYPE_TAG,
+                                        ATypeTag.SERIALIZED_RECORD_TYPE_TAG);
+                        }
+                    }
+                };
+            }
+        };
+    }
+
+    @Override
+    public FunctionIdentifier getIdentifier() {
+        return BuiltinFunctions.TO_NUMBER;
+    }
+}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/17ad8759/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/functions/FunctionCollection.java
----------------------------------------------------------------------
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 c47a4de..b94f55e 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
@@ -257,6 +257,7 @@ import org.apache.asterix.runtime.evaluators.functions.SwitchCaseDescriptor;
 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.ToStringDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.UUIDDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.WordTokensDescriptor;
@@ -728,6 +729,7 @@ public final class FunctionCollection {
         fc.addGenerated(ToStringDescriptor.FACTORY);
         fc.addGenerated(ToDoubleDescriptor.FACTORY);
         fc.addGenerated(ToBigIntDescriptor.FACTORY);
+        fc.addGenerated(ToNumberDescriptor.FACTORY);
 
         // Cast function
         fc.addGenerated(CastTypeDescriptor.FACTORY);