Dmitry Lychagin has uploaded a new change for review.

  https://asterix-gerrit.ics.uci.edu/2449

Change subject: [NO ISSUE][FUN] Add to_number() function
......................................................................

[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
---
A 
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/to_number_01/to_number_01.1.query.sqlpp
A 
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/to_number_02/to_number_02.1.query.sqlpp
A 
asterixdb/asterix-app/src/test/resources/runtimets/results/types/to_number_01/to_number_01.1.adm
M asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
M asterixdb/asterix-doc/src/main/markdown/builtins/11_type.md
M 
asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/CommonFunctionMapUtil.java
M 
asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/BuiltinFunctions.java
A 
asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/ToBigIntTypeComputer.java
A 
asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/ToDoubleTypeComputer.java
A 
asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/ToNumberTypeComputer.java
M asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/AUnionType.java
A 
asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/common/NumberUtils.java
M 
asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/constructors/AFloatConstructorDescriptor.java
M 
asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/constructors/AbstractDoubleConstructorEvaluator.java
M 
asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/constructors/AbstractInt64ConstructorEvaluator.java
M 
asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/constructors/AbstractStringConstructorEvaluator.java
M 
asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ToBigIntDescriptor.java
M 
asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ToBooleanDescriptor.java
M 
asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ToDoubleDescriptor.java
A 
asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ToNumberDescriptor.java
M 
asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/functions/FunctionCollection.java
21 files changed, 601 insertions(+), 127 deletions(-)


  git pull ssh://asterix-gerrit.ics.uci.edu:29418/asterixdb 
refs/changes/49/2449/1

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")))
+ };
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
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
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 dd1ae0c..9a7df0b 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
@@ -9280,6 +9280,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">
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:
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 5556ea9..0808e01 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 @@
         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
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.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 @@
             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 @@
 
         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);
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..d9d6467
--- /dev/null
+++ 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/ToBigIntTypeComputer.java
@@ -0,0 +1,56 @@
+/*
+ * 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 {
+        if (strippedInputTypes.length != 1) {
+            throw new IllegalArgumentException();
+        }
+        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);
+        }
+    }
+}
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..78a52a9
--- /dev/null
+++ 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/ToDoubleTypeComputer.java
@@ -0,0 +1,56 @@
+/*
+ * 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 {
+        if (strippedInputTypes.length != 1) {
+            throw new IllegalArgumentException();
+        }
+        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);
+        }
+    }
+}
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..5ae5d3c
--- /dev/null
+++ 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/ToNumberTypeComputer.java
@@ -0,0 +1,56 @@
+/*
+ * 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 {
+        if (strippedInputTypes.length != 1) {
+            throw new IllegalArgumentException();
+        }
+        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;
+        }
+    }
+}
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 @@
         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;
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() {
+    }
+}
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 @@
 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.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.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 @@
                                 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);
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.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;
@@ -43,10 +44,6 @@
     @SuppressWarnings("unchecked")
     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;
@@ -77,41 +74,25 @@
 
     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();
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.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 @@
         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);
         }
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.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 @@
                 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 @@
                 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));
                     }
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 @@
 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.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 @@
             @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 @@
                             case ARRAY:
                             case MULTISET:
                             case OBJECT:
-                                setNull(result);
+                                PointableHelper.setNull(result);
                                 break;
 
                             default:
@@ -104,13 +96,8 @@
                     }
 
                     @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
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.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;
@@ -44,12 +45,6 @@
 
 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
@@ -117,7 +112,8 @@
 
                     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);
                     }
 
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 @@
 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.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 @@
             @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 @@
                             case ARRAY:
                             case MULTISET:
                             case OBJECT:
-                                setNull(result);
+                                PointableHelper.setNull(result);
                                 break;
 
                             default:
@@ -98,14 +90,8 @@
                     }
 
                     @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
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;
+    }
+}
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.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 @@
         fc.addGenerated(ToStringDescriptor.FACTORY);
         fc.addGenerated(ToDoubleDescriptor.FACTORY);
         fc.addGenerated(ToBigIntDescriptor.FACTORY);
+        fc.addGenerated(ToNumberDescriptor.FACTORY);
 
         // Cast function
         fc.addGenerated(CastTypeDescriptor.FACTORY);

-- 
To view, visit https://asterix-gerrit.ics.uci.edu/2449
To unsubscribe, visit https://asterix-gerrit.ics.uci.edu/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Id370aadcf16447f7c775c30d2bffc33fc6a96927
Gerrit-PatchSet: 1
Gerrit-Project: asterixdb
Gerrit-Branch: master
Gerrit-Owner: Dmitry Lychagin <dmitry.lycha...@couchbase.com>

Reply via email to