Repository: asterixdb
Updated Branches:
  refs/heads/master c807e1c43 -> 3f6d3709b


[ASTERIXDB-2291][FUN] Implement if_inf,if_nan,if_nan_or_inf

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

Details:
- Implement functions: if_inf(), if_nan(), if_nan_or_inf()
- Add testcases and documentation
- INF to string conversion should produce "INF" instead of "Infinity"
- Move if_missing(), if_null() testcases to 'null-missing' folder

Change-Id: I12dccd848a1d6b4ba102bea3b7602c2cbd8aaef5
Reviewed-on: https://asterix-gerrit.ics.uci.edu/2411
Tested-by: Jenkins <jenk...@fulliautomatix.ics.uci.edu>
Integration-Tests: Jenkins <jenk...@fulliautomatix.ics.uci.edu>
Contrib: Jenkins <jenk...@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/3f6d3709
Tree: http://git-wip-us.apache.org/repos/asf/asterixdb/tree/3f6d3709
Diff: http://git-wip-us.apache.org/repos/asf/asterixdb/diff/3f6d3709

Branch: refs/heads/master
Commit: 3f6d3709b2e80991d0321e955314cd1011f6866e
Parents: c807e1c
Author: Dmitry Lychagin <dmitry.lycha...@couchbase.com>
Authored: Thu Feb 22 14:09:59 2018 -0800
Committer: Dmitry Lychagin <dmitry.lycha...@couchbase.com>
Committed: Thu Feb 22 19:01:33 2018 -0800

----------------------------------------------------------------------
 .../types/to_string_01/to_string_01.1.query.aql |   8 +-
 .../ifmissing/ifmissing.1.query.sqlpp           |  33 +++++
 .../ifmissingornull.1.query.sqlpp               |  36 +++++
 .../null-missing/ifnull/ifnull.1.query.sqlpp    |  34 +++++
 .../numeric/ifinf/ifinf.1.query.sqlpp           |  44 ++++++
 .../numeric/ifnan/ifnan.1.query.sqlpp           |  43 ++++++
 .../numeric/ifnanorinf/ifnanorinf.1.query.sqlpp |  43 ++++++
 .../types/ifmissing/ifmissing.1.query.sqlpp     |  33 -----
 .../ifmissingornull.1.query.sqlpp               |  36 -----
 .../types/ifnull/ifnull.1.query.sqlpp           |  34 -----
 .../to_string_01/to_string_01.1.query.sqlpp     |   8 +-
 .../null-missing/ifmissing/ifmissing.1.adm      |   1 +
 .../ifmissingornull/ifmissingornull.1.adm       |   1 +
 .../results/null-missing/ifnull/ifnull.1.adm    |   1 +
 .../runtimets/results/numeric/ifinf/ifinf.1.adm |  21 +++
 .../runtimets/results/numeric/ifnan/ifnan.1.adm |  20 +++
 .../results/numeric/ifnanorinf/ifnanorinf.1.adm |  20 +++
 .../results/types/ifmissing/ifmissing.1.adm     |   1 -
 .../types/ifmissingornull/ifmissingornull.1.adm |   1 -
 .../runtimets/results/types/ifnull/ifnull.1.adm |   1 -
 .../types/to_string_01/to_string_01.1.adm       |   2 +-
 .../resources/runtimets/testsuite_sqlpp.xml     |  45 ++++---
 .../main/markdown/builtins/13_conditional.md    |  98 ++++++++++++++
 .../lang/common/util/CommonFunctionMapUtil.java |   5 +-
 .../asterix/om/functions/BuiltinFunctions.java  |  10 ++
 .../base/AbstractResultTypeComputer.java        |  10 +-
 .../impl/IfNanOrInfTypeComputer.java            |  74 ++++++++++
 .../AFloatConstructorDescriptor.java            |  21 ++-
 .../AbstractDoubleConstructorEvaluator.java     |  22 ++-
 .../AbstractStringConstructorEvaluator.java     |  20 ++-
 .../evaluators/functions/IfInfDescriptor.java   |  67 +++++++++
 .../functions/IfMissingDescriptor.java          |   2 +-
 .../functions/IfMissingOrNullDescriptor.java    |  11 +-
 .../evaluators/functions/IfNanDescriptor.java   |  67 +++++++++
 .../functions/IfNanOrInfDescriptor.java         | 135 +++++++++++++++++++
 .../evaluators/functions/IfNullDescriptor.java  |   2 +-
 .../evaluators/functions/PointableHelper.java   |   8 ++
 .../runtime/functions/FunctionCollection.java   |   6 +
 38 files changed, 863 insertions(+), 161 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3f6d3709/asterixdb/asterix-app/src/test/resources/runtimets/queries/types/to_string_01/to_string_01.1.query.aql
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries/types/to_string_01/to_string_01.1.query.aql
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries/types/to_string_01/to_string_01.1.query.aql
index 2abf4c3..ee5ed6f 100644
--- 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries/types/to_string_01/to_string_01.1.query.aql
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries/types/to_string_01/to_string_01.1.query.aql
@@ -30,5 +30,11 @@
   "t11": is_null(to_string({{}})),
   "t12": is_null(to_string({})),
   "t13": is_null(to_string(null)),
-  "t14": is_missing(to_string(missing))
+  "t14": is_missing(to_string(missing)),
+  "t15": to_string(double("NaN")),
+  "t16": to_string(float("NaN")),
+  "t17": to_string(double("INF")),
+  "t18": to_string(float("INF")),
+  "t19": to_string(double("-INF")),
+  "t20": to_string(float("-INF"))
  }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3f6d3709/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/null-missing/ifmissing/ifmissing.1.query.sqlpp
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/null-missing/ifmissing/ifmissing.1.query.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/null-missing/ifmissing/ifmissing.1.query.sqlpp
new file mode 100644
index 0000000..2f0d837
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/null-missing/ifmissing/ifmissing.1.query.sqlpp
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+{
+   "a": isnull(ifmissing()),
+   "b": isnull(ifmissing(missing)),
+   "c": isnull(ifmissing(missing, missing)),
+   "d": ifmissing(missing, missing, true, 1),
+   "e": ifmissing(true, false, 1),
+   "f": isstring(ifmissing("true", true, 1)),
+   "g": if_missing(missing, true, 1),
+   "i": ifmissing(
+            missing,
+            case when get_year(current_datetime()) > 0 then missing else false 
end,
+            case when get_year(current_datetime()) > 0 then true else null end
+        )
+};

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3f6d3709/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/null-missing/ifmissingornull/ifmissingornull.1.query.sqlpp
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/null-missing/ifmissingornull/ifmissingornull.1.query.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/null-missing/ifmissingornull/ifmissingornull.1.query.sqlpp
new file mode 100644
index 0000000..32f040f
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/null-missing/ifmissingornull/ifmissingornull.1.query.sqlpp
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+{
+   "a": isnull(ifmissingornull()),
+   "b": isnull(ifmissingornull(missing)),
+   "c": isnull(ifmissingornull(null)),
+   "d": isnull(ifmissingornull(null, missing)),
+   "e": ifmissingornull(null, true, 1),
+   "f": ifmissingornull(missing, true, 1),
+   "g": ifmissingornull(null, missing, true, 1),
+   "h": if_missing_or_null(null, missing, true, 1),
+   "i": ifmissingornull(
+            missing,
+            null,
+            case when get_year(current_datetime()) > 0 then missing else false 
end,
+            case when get_year(current_datetime()) > 0 then null else false 
end,
+            case when get_year(current_datetime()) > 0 then true else missing 
end
+        )
+};
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3f6d3709/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/null-missing/ifnull/ifnull.1.query.sqlpp
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/null-missing/ifnull/ifnull.1.query.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/null-missing/ifnull/ifnull.1.query.sqlpp
new file mode 100644
index 0000000..c0683bd
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/null-missing/ifnull/ifnull.1.query.sqlpp
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+{
+   "a": isnull(null),
+   "b": isnull(ifnull()),
+   "c": isnull(ifnull(null)),
+   "d": ismissing(ifnull(missing)),
+   "e": ifnull(null, true, 1),
+   "f": ifnull(null, null, true, 1),
+   "g": ismissing(ifnull(missing, false, 1)),
+   "h": if_null(null, true),
+   "i": ifnull(
+            null,
+            case when get_year(current_datetime()) > 0 then null else false 
end,
+            case when get_year(current_datetime()) > 0 then true else missing 
end
+        )
+};

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3f6d3709/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/ifinf/ifinf.1.query.sqlpp
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/ifinf/ifinf.1.query.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/ifinf/ifinf.1.query.sqlpp
new file mode 100644
index 0000000..3b12ead
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/ifinf/ifinf.1.query.sqlpp
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+select value t
+from [
+    [ 0, isnull(ifinf()) ],
+    [ 1, isnull(ifinf(null)) ],
+    [ 2, ismissing(ifinf(missing)) ],
+    [ 3, isnull(ifinf(double("INF"))) ],
+    [ 4, isnull(ifinf(double("-INF"))) ],
+    [ 5, isnull(ifinf(float("INF"))) ],
+    [ 6, isnull(ifinf(float("-INF"))) ],
+    [ 7, ifinf(tinyint("1")) ],
+    [ 8, ifinf(smallint("2")) ],
+    [ 9, ifinf(integer("3")) ],
+    [ 10, ifinf(bigint("4")) ],
+    [ 11, ifinf(float("1.5")) ],
+    [ 12, ifinf(double("2.5")) ],
+    [ 13, ifinf(2, null, missing) ],
+    [ 14, isnull(ifinf(null, missing, 2)) ],
+    [ 15, ismissing(ifinf(missing, null, 2)) ],
+    [ 16, ifinf(double("INF"), float("-INF"), 2) ],
+    [ 17, ifinf(float("INF"), double("-INF"), 2) ],
+    [ 18, isnull(ifinf(double("INF"), double("-INF"), [], 2)) ],
+    [ 19, ismissing(if_inf(double("INF"), double("-INF"), missing, 2)) ],
+    [ 20, tostring(ifinf(float("INF"), float("NaN"), 2)) ]
+] t
+order by t[0]
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3f6d3709/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/ifnan/ifnan.1.query.sqlpp
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/ifnan/ifnan.1.query.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/ifnan/ifnan.1.query.sqlpp
new file mode 100644
index 0000000..40a55d1
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/ifnan/ifnan.1.query.sqlpp
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+select value t
+from [
+    [ 0, isnull(ifnan()) ],
+    [ 1, isnull(ifnan(null)) ],
+    [ 2, ismissing(ifnan(missing)) ],
+    [ 3, isnull(ifnan(double("NaN"))) ],
+    [ 5, isnull(ifnan(float("NaN"))) ],
+    [ 7, ifnan(tinyint("1")) ],
+    [ 8, ifnan(smallint("2")) ],
+    [ 9, ifnan(integer("3")) ],
+    [ 10, ifnan(bigint("4")) ],
+    [ 11, ifnan(float("1.5")) ],
+    [ 12, ifnan(double("2.5")) ],
+    [ 13, ifnan(2, null, missing) ],
+    [ 14, isnull(ifnan(null, missing, 2)) ],
+    [ 15, ismissing(ifnan(missing, null, 2)) ],
+    [ 16, ifnan(double("NaN"), 2) ],
+    [ 17, ifnan(float("NaN"), 2) ],
+    [ 18, isnull(ifnan(double("NaN"), [], 2)) ],
+    [ 19, ismissing(if_nan(double("NaN"), missing, 2)) ],
+    [ 20, tostring(ifnan(double("NaN"), double("INF"), 2)) ],
+    [ 21, tostring(ifnan(float("NaN"), float("-INF"), 2)) ]
+] t
+order by t[0]
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3f6d3709/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/ifnanorinf/ifnanorinf.1.query.sqlpp
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/ifnanorinf/ifnanorinf.1.query.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/ifnanorinf/ifnanorinf.1.query.sqlpp
new file mode 100644
index 0000000..d4b1863
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/ifnanorinf/ifnanorinf.1.query.sqlpp
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+select value t
+from [
+    [ 0, isnull(ifnanorinf()) ],
+    [ 1, isnull(ifnanorinf(null)) ],
+    [ 2, ismissing(ifnanorinf(missing)) ],
+    [ 3, isnull(ifnanorinf(double("NaN"))) ],
+    [ 5, isnull(ifnanorinf(float("INF"))) ],
+    [ 7, ifnanorinf(tinyint("1")) ],
+    [ 8, ifnanorinf(smallint("2")) ],
+    [ 9, ifnanorinf(integer("3")) ],
+    [ 10, ifnanorinf(bigint("4")) ],
+    [ 11, ifnanorinf(float("1.5")) ],
+    [ 12, ifnanorinf(double("2.5")) ],
+    [ 13, ifnanorinf(2, null, missing) ],
+    [ 14, isnull(ifnanorinf(null, missing, 2)) ],
+    [ 15, ismissing(ifnanorinf(missing, null, 2)) ],
+    [ 16, ifnanorinf(double("-INF"), 2) ],
+    [ 17, ifnanorinf(float("NaN"), 2) ],
+    [ 18, isnull(ifnanorinf(double("NaN"), [], 2)) ],
+    [ 19, ismissing(if_nan_or_inf(double("NaN"), missing, 2)) ],
+    [ 20, ifnanorinf(double("NaN"), double("INF"), 2) ],
+    [ 21, ifnanorinf(float("NaN"), float("-INF"), 2) ]
+] t
+order by t[0]
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3f6d3709/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/ifmissing/ifmissing.1.query.sqlpp
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/ifmissing/ifmissing.1.query.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/ifmissing/ifmissing.1.query.sqlpp
deleted file mode 100644
index 2f0d837..0000000
--- 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/ifmissing/ifmissing.1.query.sqlpp
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-{
-   "a": isnull(ifmissing()),
-   "b": isnull(ifmissing(missing)),
-   "c": isnull(ifmissing(missing, missing)),
-   "d": ifmissing(missing, missing, true, 1),
-   "e": ifmissing(true, false, 1),
-   "f": isstring(ifmissing("true", true, 1)),
-   "g": if_missing(missing, true, 1),
-   "i": ifmissing(
-            missing,
-            case when get_year(current_datetime()) > 0 then missing else false 
end,
-            case when get_year(current_datetime()) > 0 then true else null end
-        )
-};

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3f6d3709/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/ifmissingornull/ifmissingornull.1.query.sqlpp
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/ifmissingornull/ifmissingornull.1.query.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/ifmissingornull/ifmissingornull.1.query.sqlpp
deleted file mode 100644
index 32f040f..0000000
--- 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/ifmissingornull/ifmissingornull.1.query.sqlpp
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-{
-   "a": isnull(ifmissingornull()),
-   "b": isnull(ifmissingornull(missing)),
-   "c": isnull(ifmissingornull(null)),
-   "d": isnull(ifmissingornull(null, missing)),
-   "e": ifmissingornull(null, true, 1),
-   "f": ifmissingornull(missing, true, 1),
-   "g": ifmissingornull(null, missing, true, 1),
-   "h": if_missing_or_null(null, missing, true, 1),
-   "i": ifmissingornull(
-            missing,
-            null,
-            case when get_year(current_datetime()) > 0 then missing else false 
end,
-            case when get_year(current_datetime()) > 0 then null else false 
end,
-            case when get_year(current_datetime()) > 0 then true else missing 
end
-        )
-};
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3f6d3709/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/ifnull/ifnull.1.query.sqlpp
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/ifnull/ifnull.1.query.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/ifnull/ifnull.1.query.sqlpp
deleted file mode 100644
index c0683bd..0000000
--- 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/ifnull/ifnull.1.query.sqlpp
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-{
-   "a": isnull(null),
-   "b": isnull(ifnull()),
-   "c": isnull(ifnull(null)),
-   "d": ismissing(ifnull(missing)),
-   "e": ifnull(null, true, 1),
-   "f": ifnull(null, null, true, 1),
-   "g": ismissing(ifnull(missing, false, 1)),
-   "h": if_null(null, true),
-   "i": ifnull(
-            null,
-            case when get_year(current_datetime()) > 0 then null else false 
end,
-            case when get_year(current_datetime()) > 0 then true else missing 
end
-        )
-};

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3f6d3709/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/to_string_01/to_string_01.1.query.sqlpp
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/to_string_01/to_string_01.1.query.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/to_string_01/to_string_01.1.query.sqlpp
index 8582521..f759e16 100644
--- 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/to_string_01/to_string_01.1.query.sqlpp
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/types/to_string_01/to_string_01.1.query.sqlpp
@@ -30,5 +30,11 @@
   "t11": is_null(to_string({{}})),
   "t12": is_null(to_string({})),
   "t13": is_null(to_string(null)),
-  "t14": is_missing(to_string(missing))
+  "t14": is_missing(to_string(missing)),
+  "t15": to_string(double("NaN")),
+  "t16": to_string(float("NaN")),
+  "t17": to_string(double("INF")),
+  "t18": to_string(float("INF")),
+  "t19": to_string(double("-INF")),
+  "t20": to_string(float("-INF"))
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3f6d3709/asterixdb/asterix-app/src/test/resources/runtimets/results/null-missing/ifmissing/ifmissing.1.adm
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/null-missing/ifmissing/ifmissing.1.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/null-missing/ifmissing/ifmissing.1.adm
new file mode 100644
index 0000000..0a2275f
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/null-missing/ifmissing/ifmissing.1.adm
@@ -0,0 +1 @@
+{ "a": true, "b": true, "c": true, "d": true, "e": true, "f": true, "g": true, 
"i": true }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3f6d3709/asterixdb/asterix-app/src/test/resources/runtimets/results/null-missing/ifmissingornull/ifmissingornull.1.adm
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/null-missing/ifmissingornull/ifmissingornull.1.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/null-missing/ifmissingornull/ifmissingornull.1.adm
new file mode 100644
index 0000000..633c503
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/null-missing/ifmissingornull/ifmissingornull.1.adm
@@ -0,0 +1 @@
+{ "a": true, "b": true, "c": true, "d": true, "e": true, "f": true, "g": true, 
"h": true, "i": true }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3f6d3709/asterixdb/asterix-app/src/test/resources/runtimets/results/null-missing/ifnull/ifnull.1.adm
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/null-missing/ifnull/ifnull.1.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/null-missing/ifnull/ifnull.1.adm
new file mode 100644
index 0000000..633c503
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/null-missing/ifnull/ifnull.1.adm
@@ -0,0 +1 @@
+{ "a": true, "b": true, "c": true, "d": true, "e": true, "f": true, "g": true, 
"h": true, "i": true }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3f6d3709/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/ifinf/ifinf.1.adm
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/ifinf/ifinf.1.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/ifinf/ifinf.1.adm
new file mode 100644
index 0000000..c45efa6
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/ifinf/ifinf.1.adm
@@ -0,0 +1,21 @@
+[ 0, true ]
+[ 1, true ]
+[ 2, true ]
+[ 3, true ]
+[ 4, true ]
+[ 5, true ]
+[ 6, true ]
+[ 7, 1 ]
+[ 8, 2 ]
+[ 9, 3 ]
+[ 10, 4 ]
+[ 11, 1.5 ]
+[ 12, 2.5 ]
+[ 13, 2 ]
+[ 14, true ]
+[ 15, true ]
+[ 16, 2 ]
+[ 17, 2 ]
+[ 18, true ]
+[ 19, true ]
+[ 20, "NaN" ]
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3f6d3709/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/ifnan/ifnan.1.adm
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/ifnan/ifnan.1.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/ifnan/ifnan.1.adm
new file mode 100644
index 0000000..ec02746
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/ifnan/ifnan.1.adm
@@ -0,0 +1,20 @@
+[ 0, true ]
+[ 1, true ]
+[ 2, true ]
+[ 3, true ]
+[ 5, true ]
+[ 7, 1 ]
+[ 8, 2 ]
+[ 9, 3 ]
+[ 10, 4 ]
+[ 11, 1.5 ]
+[ 12, 2.5 ]
+[ 13, 2 ]
+[ 14, true ]
+[ 15, true ]
+[ 16, 2 ]
+[ 17, 2 ]
+[ 18, true ]
+[ 19, true ]
+[ 20, "INF" ]
+[ 21, "-INF" ]
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3f6d3709/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/ifnanorinf/ifnanorinf.1.adm
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/ifnanorinf/ifnanorinf.1.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/ifnanorinf/ifnanorinf.1.adm
new file mode 100644
index 0000000..34476cc
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/ifnanorinf/ifnanorinf.1.adm
@@ -0,0 +1,20 @@
+[ 0, true ]
+[ 1, true ]
+[ 2, true ]
+[ 3, true ]
+[ 5, true ]
+[ 7, 1 ]
+[ 8, 2 ]
+[ 9, 3 ]
+[ 10, 4 ]
+[ 11, 1.5 ]
+[ 12, 2.5 ]
+[ 13, 2 ]
+[ 14, true ]
+[ 15, true ]
+[ 16, 2 ]
+[ 17, 2 ]
+[ 18, true ]
+[ 19, true ]
+[ 20, 2 ]
+[ 21, 2 ]
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3f6d3709/asterixdb/asterix-app/src/test/resources/runtimets/results/types/ifmissing/ifmissing.1.adm
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/types/ifmissing/ifmissing.1.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/types/ifmissing/ifmissing.1.adm
deleted file mode 100644
index 0a2275f..0000000
--- 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/types/ifmissing/ifmissing.1.adm
+++ /dev/null
@@ -1 +0,0 @@
-{ "a": true, "b": true, "c": true, "d": true, "e": true, "f": true, "g": true, 
"i": true }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3f6d3709/asterixdb/asterix-app/src/test/resources/runtimets/results/types/ifmissingornull/ifmissingornull.1.adm
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/types/ifmissingornull/ifmissingornull.1.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/types/ifmissingornull/ifmissingornull.1.adm
deleted file mode 100644
index 633c503..0000000
--- 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/types/ifmissingornull/ifmissingornull.1.adm
+++ /dev/null
@@ -1 +0,0 @@
-{ "a": true, "b": true, "c": true, "d": true, "e": true, "f": true, "g": true, 
"h": true, "i": true }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3f6d3709/asterixdb/asterix-app/src/test/resources/runtimets/results/types/ifnull/ifnull.1.adm
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/types/ifnull/ifnull.1.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/types/ifnull/ifnull.1.adm
deleted file mode 100644
index 633c503..0000000
--- 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/types/ifnull/ifnull.1.adm
+++ /dev/null
@@ -1 +0,0 @@
-{ "a": true, "b": true, "c": true, "d": true, "e": true, "f": true, "g": true, 
"h": true, "i": true }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3f6d3709/asterixdb/asterix-app/src/test/resources/runtimets/results/types/to_string_01/to_string_01.1.adm
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/types/to_string_01/to_string_01.1.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/types/to_string_01/to_string_01.1.adm
index 83dee03..11a3abb 100644
--- 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/types/to_string_01/to_string_01.1.adm
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/types/to_string_01/to_string_01.1.adm
@@ -1 +1 @@
-{ "t1": "false", "t2": "true", "t3": "8", "t4": "16", "t5": "32", "t6": "64", 
"t7": "128.0", "t8": "256.0", "t9": "foo", "t10": true, "t11": true, "t12": 
true, "t13": true, "t14": true }
\ No newline at end of file
+{ "t1": "false", "t2": "true", "t3": "8", "t4": "16", "t5": "32", "t6": "64", 
"t7": "128.0", "t8": "256.0", "t9": "foo", "t10": true, "t11": true, "t12": 
true, "t13": true, "t14": true, "t15": "NaN", "t16": "NaN", "t17": "INF", 
"t18": "INF", "t19": "-INF", "t20": "-INF" }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3f6d3709/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 a869b22..bb0d473 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
@@ -4648,6 +4648,21 @@
       </compilation-unit>
     </test-case>
     <test-case FilePath="null-missing">
+      <compilation-unit name="ifmissing">
+        <output-dir compare="Text">ifmissing</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="null-missing">
+      <compilation-unit name="ifnull">
+        <output-dir compare="Text">ifnull</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="null-missing">
+      <compilation-unit name="ifmissingornull">
+        <output-dir compare="Text">ifmissingornull</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="null-missing">
       <compilation-unit name="query-ASTERIXDB-1689">
         <output-dir compare="Text">query-ASTERIXDB-1689</output-dir>
       </compilation-unit>
@@ -4805,6 +4820,21 @@
       </compilation-unit>
     </test-case>
     <test-case FilePath="numeric">
+      <compilation-unit name="ifinf">
+        <output-dir compare="Text">ifinf</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="numeric">
+      <compilation-unit name="ifnan">
+        <output-dir compare="Text">ifnan</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="numeric">
+      <compilation-unit name="ifnanorinf">
+        <output-dir compare="Text">ifnanorinf</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="numeric">
       <compilation-unit name="infinity">
         <output-dir compare="Text">infinity</output-dir>
       </compilation-unit>
@@ -9182,21 +9212,6 @@
       </compilation-unit>
     </test-case>
     <test-case FilePath="types">
-      <compilation-unit name="ifmissing">
-        <output-dir compare="Text">ifmissing</output-dir>
-      </compilation-unit>
-    </test-case>
-    <test-case FilePath="types">
-      <compilation-unit name="ifnull">
-        <output-dir compare="Text">ifnull</output-dir>
-      </compilation-unit>
-    </test-case>
-    <test-case FilePath="types">
-      <compilation-unit name="ifmissingornull">
-        <output-dir compare="Text">ifmissingornull</output-dir>
-      </compilation-unit>
-    </test-case>
-    <test-case FilePath="types">
       <compilation-unit name="to_boolean_01">
         <output-dir compare="Text">to_boolean_01</output-dir>
       </compilation-unit>

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3f6d3709/asterixdb/asterix-doc/src/main/markdown/builtins/13_conditional.md
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-doc/src/main/markdown/builtins/13_conditional.md 
b/asterixdb/asterix-doc/src/main/markdown/builtins/13_conditional.md
index 202f7e4..ed9551e 100644
--- a/asterixdb/asterix-doc/src/main/markdown/builtins/13_conditional.md
+++ b/asterixdb/asterix-doc/src/main/markdown/builtins/13_conditional.md
@@ -101,3 +101,101 @@
         { "a": null, "b": null, "c": "asterixdb" }
 
  The function has an alias `ifmissingornull`.
+
+### if_inf (ifinf) ###
+
+ * Syntax:
+
+        if_inf(expression1, expression2, ... expressionN)
+
+ * Finds first argument which is a non-infinite (`INF` or`-INF`) number
+ * Arguments:
+    * `expressionI` : an expression (any type is allowed).
+ * Return Value:
+    * a `missing` if `missing` argument was encountered before the first 
non-infinite number argument
+    * a `null` if `null` argument or any other non-number argument was 
encountered before the first non-infinite number argument
+    * the first non-infinite number argument otherwise
+
+ * Example:
+
+        {
+            "a": is_null(if_inf(null)),
+            "b": is_missing(if_inf(missing)),
+            "c": is_null(if_inf(double("INF"))),
+            "d": if_inf(1, null, missing) ],
+            "e": is_null(if_inf(null, missing, 1)) ],
+            "f": is_missing(if_inf(missing, null, 1)) ],
+            "g": if_inf(float("INF"), 1) ],
+            "h": to_string(if_inf(float("INF"), double("NaN"), 1)) ]
+        };
+
+ * The expected result is:
+
+        { "a": true, "b": true, "c": true, "d": 1, "e": true, "f": true, "g": 
1, "h": "NaN" }
+
+ The function has an alias `ifinf`.
+
+### if_nan (ifnan) ###
+
+ * Syntax:
+
+        if_nan(expression1, expression2, ... expressionN)
+
+ * Finds first argument which is a non-`NaN` number
+ * Arguments:
+    * `expressionI` : an expression (any type is allowed).
+ * Return Value:
+    * a `missing` if `missing` argument was encountered before the first 
non-`NaN` number argument
+    * a `null` if `null` argument or any other non-number argument was 
encountered before the first non-`NaN` number argument
+    * the first non-`NaN` number argument otherwise
+
+ * Example:
+
+        {
+            "a": is_null(if_nan(null)),
+            "b": is_missing(if_nan(missing)),
+            "c": is_null(if_nan(double("NaN"))),
+            "d": if_nan(1, null, missing) ],
+            "e": is_null(if_nan(null, missing, 1)) ],
+            "f": is_missing(if_nan(missing, null, 1)) ],
+            "g": if_nan(float("NaN"), 1) ],
+            "h": to_string(if_nan(float("NaN"), double("INF"), 1)) ]
+        };
+
+ * The expected result is:
+
+        { "a": true, "b": true, "c": true, "d": 1, "e": true, "f": true, "g": 
1, "h": "INF" }
+
+ The function has an alias `ifnan`.
+
+### if_nan_or_inf (ifnanorinf) ###
+
+ * Syntax:
+
+        if_nan_or_inf(expression1, expression2, ... expressionN)
+
+ * Finds first argument which is a non-infinite (`INF` or`-INF`) and non-`NaN` 
number
+ * Arguments:
+    * `expressionI` : an expression (any type is allowed).
+ * Return Value:
+    * a `missing` if `missing` argument was encountered before the first 
non-infinite and non-`NaN` number argument
+    * a `null` if `null` argument or any other non-number argument was 
encountered before the first non-infinite and non-`NaN` number argument
+    * the first non-infinite and non-`NaN` number argument otherwise
+
+ * Example:
+
+        {
+            "a": is_null(if_nan_or_inf(null)),
+            "b": is_missing(if_nan_or_inf(missing)),
+            "c": is_null(if_nan_or_inf(double("NaN"), double("INF"))),
+            "d": if_nan_or_inf(1, null, missing) ],
+            "e": is_null(if_nan_or_inf(null, missing, 1)) ],
+            "f": is_missing(if_nan_or_inf(missing, null, 1)) ],
+            "g": if_nan_or_inf(float("NaN"), float("INF"), 1) ],
+        };
+
+ * The expected result is:
+
+        { "a": true, "b": true, "c": true, "d": 1, "e": true, "f": true, "g": 
1 }
+
+ The function has an alias `ifnanorinf`.

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3f6d3709/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 b78ee9f..5556ea9 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
@@ -66,7 +66,10 @@ public class CommonFunctionMapUtil {
         FUNCTION_NAME_MAP.put("isobj", "is-object"); // isobj, internal: 
is-object
         FUNCTION_NAME_MAP.put("ifmissing", "if-missing"); // ifmissing, 
internal: if-missing
         FUNCTION_NAME_MAP.put("ifnull", "if-null"); // ifnull, internal: 
if-null
-        FUNCTION_NAME_MAP.put("ifmissingornull", "if-missing-or-null"); // 
ifmissingornull, internal: is-missing-or-null
+        FUNCTION_NAME_MAP.put("ifmissingornull", "if-missing-or-null"); // 
ifmissingornull, internal: if-missing-or-null
+        FUNCTION_NAME_MAP.put("ifinf", "if-inf"); // ifinf, internal: if-inf
+        FUNCTION_NAME_MAP.put("ifnan", "if-nan"); // ifnan, internal: if-nan
+        FUNCTION_NAME_MAP.put("ifnanorinf", "if-nan-or-inf"); // ifnanorinf, 
internal: if-nan-or-inf
         FUNCTION_NAME_MAP.put("toboolean", "to-boolean"); // toboolean, 
internal: to-boolean
         FUNCTION_NAME_MAP.put("tostring", "to-string"); // tostring, internal: 
to-string
         FUNCTION_NAME_MAP.put("todouble", "to-double"); // todouble, internal: 
to-double

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3f6d3709/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 153ea45..761ddba 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
@@ -66,6 +66,7 @@ import 
org.apache.asterix.om.typecomputer.impl.FieldAccessByNameResultType;
 import org.apache.asterix.om.typecomputer.impl.FieldAccessNestedResultType;
 import 
org.apache.asterix.om.typecomputer.impl.FullTextContainsResultTypeComputer;
 import 
org.apache.asterix.om.typecomputer.impl.GetOverlappingInvervalTypeComputer;
+import org.apache.asterix.om.typecomputer.impl.IfNanOrInfTypeComputer;
 import org.apache.asterix.om.typecomputer.impl.IfMissingOrNullTypeComputer;
 import org.apache.asterix.om.typecomputer.impl.IfMissingTypeComputer;
 import org.apache.asterix.om.typecomputer.impl.IfNullTypeComputer;
@@ -855,6 +856,12 @@ public class BuiltinFunctions {
             new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "if-null", 
FunctionIdentifier.VARARGS);
     public static final FunctionIdentifier IF_MISSING_OR_NULL =
             new FunctionIdentifier(FunctionConstants.ASTERIX_NS, 
"if-missing-or-null", FunctionIdentifier.VARARGS);
+    public static final FunctionIdentifier IF_INF =
+            new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "if-inf", 
FunctionIdentifier.VARARGS);
+    public static final FunctionIdentifier IF_NAN =
+            new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "if-nan", 
FunctionIdentifier.VARARGS);
+    public static final FunctionIdentifier IF_NAN_OR_INF =
+            new FunctionIdentifier(FunctionConstants.ASTERIX_NS, 
"if-nan-or-inf", FunctionIdentifier.VARARGS);
 
     public static final FunctionIdentifier TO_BOOLEAN =
             new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "to-boolean", 
1);
@@ -992,6 +999,9 @@ public class BuiltinFunctions {
         addFunction(NUMERIC_ROUND_HALF_TO_EVEN, 
NumericUnaryFunctionTypeComputer.INSTANCE, true);
         addFunction(NUMERIC_ROUND_HALF_TO_EVEN2, 
NumericRound2TypeComputer.INSTANCE, true);
         addFunction(NUMERIC_TRUNC, NumericRound2TypeComputer.INSTANCE, true);
+        addFunction(IF_INF, IfNanOrInfTypeComputer.INSTANCE, true);
+        addFunction(IF_NAN, IfNanOrInfTypeComputer.INSTANCE, true);
+        addFunction(IF_NAN_OR_INF, IfNanOrInfTypeComputer.INSTANCE, true);
 
         addFunction(BINARY_LENGTH, UnaryBinaryInt64TypeComputer.INSTANCE, 
true);
         addFunction(PARSE_BINARY, ABinaryTypeComputer.INSTANCE, true);

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3f6d3709/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/base/AbstractResultTypeComputer.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/base/AbstractResultTypeComputer.java
 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/base/AbstractResultTypeComputer.java
index f33db4b..4d6b7e6 100644
--- 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/base/AbstractResultTypeComputer.java
+++ 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/base/AbstractResultTypeComputer.java
@@ -40,7 +40,7 @@ public abstract class AbstractResultTypeComputer implements 
IResultTypeComputer
         AbstractFunctionCallExpression functionCallExpression = 
(AbstractFunctionCallExpression) expression;
         String funcName = 
functionCallExpression.getFunctionIdentifier().getName();
         return TypeComputeUtils.resolveResultType(expression, env, (index, 
type) -> checkArgType(funcName, index, type),
-                this::getResultType, true);
+                this::getResultType, propagateNullAndMissing());
     }
 
     /**
@@ -70,4 +70,12 @@ public abstract class AbstractResultTypeComputer implements 
IResultTypeComputer
      */
     protected abstract IAType getResultType(ILogicalExpression expr, IAType... 
strippedInputTypes)
             throws AlgebricksException;
+
+    /**
+     * Whether the expression follows MISSING-in-MISSING-out and 
NULL-in-NULL-out semantics
+     * @return said value
+     */
+    protected boolean propagateNullAndMissing() {
+        return true;
+    }
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3f6d3709/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/IfNanOrInfTypeComputer.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/IfNanOrInfTypeComputer.java
 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/IfNanOrInfTypeComputer.java
new file mode 100644
index 0000000..bb9fa38
--- /dev/null
+++ 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/IfNanOrInfTypeComputer.java
@@ -0,0 +1,74 @@
+/*
+ * 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 IfNanOrInfTypeComputer extends AbstractResultTypeComputer {
+
+    public static final IfNanOrInfTypeComputer INSTANCE = new 
IfNanOrInfTypeComputer();
+
+    @Override
+    protected IAType getResultType(ILogicalExpression expr, IAType... 
strippedInputTypes) throws AlgebricksException {
+        if (strippedInputTypes.length == 0) {
+            return BuiltinType.ANULL;
+        }
+
+        boolean any = false;
+        IAType currentType = null;
+        for (IAType type : strippedInputTypes) {
+            if (currentType != null && !type.equals(currentType)) {
+                any = true;
+                break;
+            }
+            currentType = type;
+        }
+        if (any || currentType == null) {
+            return BuiltinType.ANY;
+        }
+
+        switch (currentType.getTypeTag()) {
+            case ANY:
+            case MISSING:
+            case BIGINT:
+            case INTEGER:
+            case SMALLINT:
+            case TINYINT:
+                return currentType;
+
+            case DOUBLE:
+            case FLOAT:
+                return AUnionType.createNullableType(currentType, null);
+
+            default:
+                return BuiltinType.ANULL;
+        }
+    }
+
+    @Override
+    protected boolean propagateNullAndMissing() {
+        return false;
+    }
+}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3f6d3709/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 ffc982a..8c69671 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
@@ -68,11 +68,6 @@ public class AFloatConstructorDescriptor extends 
AbstractScalarFunctionDynamicDe
                     private DataOutput out = resultStorage.getDataOutput();
                     private IPointable inputArg = new VoidPointable();
                     private IScalarEvaluator eval = 
args[0].createScalarEvaluator(ctx);
-                    private final byte[] POSITIVE_INF = 
UTF8StringUtil.writeStringToBytes("INF");
-                    private final byte[] NEGATIVE_INF = 
UTF8StringUtil.writeStringToBytes("-INF");
-                    private final byte[] NAN = 
UTF8StringUtil.writeStringToBytes("NaN");
-                    private IBinaryComparator utf8BinaryComparator =
-                            
BinaryComparatorFactoryProvider.UTF8STRING_POINTABLE_INSTANCE.createBinaryComparator();
                     private AMutableFloat aFloat = new AMutableFloat(0);
                     @SuppressWarnings("unchecked")
                     private ISerializerDeserializer<AFloat> floatSerde =
@@ -92,17 +87,19 @@ public class AFloatConstructorDescriptor extends 
AbstractScalarFunctionDynamicDe
                                 result.set(inputArg);
                             } else if (tt == 
ATypeTag.SERIALIZED_STRING_TYPE_TAG) {
                                 resultStorage.reset();
-                                if (utf8BinaryComparator.compare(serString, 
offset + 1, len - 1, POSITIVE_INF, 0,
-                                        5) == 0) {
+                                int utf8offset = offset + 1;
+                                int utf8len = len - 1;
+                                if 
(AbstractDoubleConstructorEvaluator.POSITIVE_INF.compareTo(serString, 
utf8offset,
+                                        utf8len) == 0) {
                                     aFloat.setValue(Float.POSITIVE_INFINITY);
-                                } else if 
(utf8BinaryComparator.compare(serString, offset + 1, len - 1, NEGATIVE_INF, 0,
-                                        6) == 0) {
+                                } else if 
(AbstractDoubleConstructorEvaluator.NEGATIVE_INF.compareTo(serString,
+                                        utf8offset, utf8len) == 0) {
                                     aFloat.setValue(Float.NEGATIVE_INFINITY);
-                                } else if 
(utf8BinaryComparator.compare(serString, offset + 1, len - 1, NAN, 0,
-                                        5) == 0) {
+                                } else if 
(AbstractDoubleConstructorEvaluator.NAN.compareTo(serString, utf8offset,
+                                        utf8len) == 0) {
                                     aFloat.setValue(Float.NaN);
                                 } else {
-                                    utf8Ptr.set(serString, offset + 1, len - 
1);
+                                    utf8Ptr.set(serString, utf8offset, 
utf8len);
                                     
aFloat.setValue(Float.parseFloat(utf8Ptr.toString()));
                                 }
                                 floatSerde.serialize(aFloat, out);

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3f6d3709/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 332bfc2..e10bf68 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
@@ -22,7 +22,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.ADouble;
 import org.apache.asterix.om.base.AMutableDouble;
@@ -32,7 +31,6 @@ 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.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;
@@ -40,19 +38,15 @@ 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 abstract class AbstractDoubleConstructorEvaluator implements 
IScalarEvaluator {
     @SuppressWarnings("unchecked")
     protected static final ISerializerDeserializer<ADouble> DOUBLE_SERDE =
             
SerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.ADOUBLE);
 
-    protected static final IBinaryComparator UTF8_BINARY_CMP =
-            
BinaryComparatorFactoryProvider.UTF8STRING_POINTABLE_INSTANCE.createBinaryComparator();
-
-    protected static final byte[] POSITIVE_INF = 
UTF8StringUtil.writeStringToBytes("INF");
-    protected static final byte[] NEGATIVE_INF = 
UTF8StringUtil.writeStringToBytes("-INF");
-    protected static final byte[] NAN = 
UTF8StringUtil.writeStringToBytes("NaN");
+    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;
@@ -89,14 +83,16 @@ public abstract class AbstractDoubleConstructorEvaluator 
implements IScalarEvalu
             result.set(inputArg);
         } else if (tt == ATypeTag.SERIALIZED_STRING_TYPE_TAG) {
             int len = inputArg.getLength();
-            if (UTF8_BINARY_CMP.compare(bytes, offset + 1, len - 1, 
POSITIVE_INF, 0, 5) == 0) {
+            int utf8offset = offset + 1;
+            int utf8len = len - 1;
+            if (POSITIVE_INF.compareTo(bytes, utf8offset, utf8len) == 0) {
                 setDouble(result, Double.POSITIVE_INFINITY);
-            } else if (UTF8_BINARY_CMP.compare(bytes, offset + 1, len - 1, 
NEGATIVE_INF, 0, 6) == 0) {
+            } else if (NEGATIVE_INF.compareTo(bytes, utf8offset, utf8len) == 
0) {
                 setDouble(result, Double.NEGATIVE_INFINITY);
-            } else if (UTF8_BINARY_CMP.compare(bytes, offset + 1, len - 1, 
NAN, 0, 5) == 0) {
+            } else if (NAN.compareTo(bytes, utf8offset, utf8len) == 0) {
                 setDouble(result, Double.NaN);
             } else {
-                utf8Ptr.set(bytes, offset + 1, len - 1);
+                utf8Ptr.set(bytes, utf8offset, utf8len);
                 try {
                     setDouble(result, Double.parseDouble(utf8Ptr.toString()));
                 } catch (NumberFormatException e) {

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3f6d3709/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 6918bb9..11576aa 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
@@ -106,12 +106,28 @@ public abstract class AbstractStringConstructorEvaluator 
implements IScalarEvalu
                 }
                 case DOUBLE: {
                     double d = 
ADoubleSerializerDeserializer.getDouble(serString, startOffset);
-                    builder.appendString(String.valueOf(d));
+                    if (Double.isNaN(d)) {
+                        
builder.appendUtf8StringPointable(AbstractDoubleConstructorEvaluator.NAN);
+                    } else if (d == Double.POSITIVE_INFINITY) { // NOSONAR
+                        
builder.appendUtf8StringPointable(AbstractDoubleConstructorEvaluator.POSITIVE_INF);
+                    } else if (d == Double.NEGATIVE_INFINITY) { // NOSONAR
+                        
builder.appendUtf8StringPointable(AbstractDoubleConstructorEvaluator.NEGATIVE_INF);
+                    } else {
+                        builder.appendString(String.valueOf(d));
+                    }
                     break;
                 }
                 case FLOAT: {
                     float f = AFloatSerializerDeserializer.getFloat(serString, 
startOffset);
-                    builder.appendString(String.valueOf(f));
+                    if (Float.isNaN(f)) {
+                        
builder.appendUtf8StringPointable(AbstractDoubleConstructorEvaluator.NAN);
+                    } else if (f == Float.POSITIVE_INFINITY) { // NOSONAR
+                        
builder.appendUtf8StringPointable(AbstractDoubleConstructorEvaluator.POSITIVE_INF);
+                    } else if (f == Float.NEGATIVE_INFINITY) { // NOSONAR
+                        
builder.appendUtf8StringPointable(AbstractDoubleConstructorEvaluator.NEGATIVE_INF);
+                    } else {
+                        builder.appendString(String.valueOf(f));
+                    }
                     break;
                 }
                 case BOOLEAN: {

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3f6d3709/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IfInfDescriptor.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IfInfDescriptor.java
 
b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IfInfDescriptor.java
new file mode 100644
index 0000000..0ff08a4
--- /dev/null
+++ 
b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IfInfDescriptor.java
@@ -0,0 +1,67 @@
+/*
+ * 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 org.apache.asterix.om.functions.BuiltinFunctions;
+import org.apache.asterix.om.functions.IFunctionDescriptorFactory;
+import 
org.apache.asterix.runtime.evaluators.base.AbstractScalarFunctionDynamicDescriptor;
+import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory;
+import org.apache.hyracks.api.context.IHyracksTaskContext;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+
+public class IfInfDescriptor extends AbstractScalarFunctionDynamicDescriptor {
+
+    private static final long serialVersionUID = 1L;
+    public static final IFunctionDescriptorFactory FACTORY = 
IfInfDescriptor::new;
+
+    @Override
+    public IScalarEvaluatorFactory createEvaluatorFactory(final 
IScalarEvaluatorFactory[] args) {
+        return new IScalarEvaluatorFactory() {
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            public IScalarEvaluator createScalarEvaluator(final 
IHyracksTaskContext ctx) throws HyracksDataException {
+                return new IfNanOrInfDescriptor.AbstractIfInfOrNanEval(ctx, 
args) {
+                    @Override
+                    protected boolean skipDouble(double d) {
+                        return Double.isInfinite(d);
+                    }
+
+                    @Override
+                    protected boolean skipFloat(float f) {
+                        return Float.isInfinite(f);
+                    }
+
+                    @Override
+                    protected FunctionIdentifier getIdentifier() {
+                        return IfInfDescriptor.this.getIdentifier();
+                    }
+                };
+            }
+        };
+    }
+
+    @Override
+    public FunctionIdentifier getIdentifier() {
+        return BuiltinFunctions.IF_INF;
+    }
+}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3f6d3709/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IfMissingDescriptor.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IfMissingDescriptor.java
 
b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IfMissingDescriptor.java
index 984b692..c3c017c 100644
--- 
a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IfMissingDescriptor.java
+++ 
b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IfMissingDescriptor.java
@@ -40,7 +40,7 @@ public class IfMissingDescriptor extends 
AbstractScalarFunctionDynamicDescriptor
 
             @Override
             public IScalarEvaluator createScalarEvaluator(final 
IHyracksTaskContext ctx) throws HyracksDataException {
-                return new IfMissingOrNullDescriptor.AbstractIfEvaluator(ctx, 
args) {
+                return new 
IfMissingOrNullDescriptor.AbstractIfMissingOrNullEval(ctx, args) {
                     @Override
                     protected boolean skip(byte argTypeTag) {
                         return argTypeTag == 
ATypeTag.SERIALIZED_MISSING_TYPE_TAG;

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3f6d3709/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IfMissingOrNullDescriptor.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IfMissingOrNullDescriptor.java
 
b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IfMissingOrNullDescriptor.java
index 28db4d6..3166c40 100644
--- 
a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IfMissingOrNullDescriptor.java
+++ 
b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IfMissingOrNullDescriptor.java
@@ -45,7 +45,7 @@ public final class IfMissingOrNullDescriptor extends 
AbstractScalarFunctionDynam
 
             @Override
             public IScalarEvaluator createScalarEvaluator(final 
IHyracksTaskContext ctx) throws HyracksDataException {
-                return new AbstractIfEvaluator(ctx, args) {
+                return new AbstractIfMissingOrNullEval(ctx, args) {
                     @Override
                     protected boolean skip(byte argTypeTag) {
                         return argTypeTag == 
ATypeTag.SERIALIZED_MISSING_TYPE_TAG
@@ -61,15 +61,14 @@ public final class IfMissingOrNullDescriptor extends 
AbstractScalarFunctionDynam
         return BuiltinFunctions.IF_MISSING_OR_NULL;
     }
 
-    public static abstract class AbstractIfEvaluator implements 
IScalarEvaluator {
-
-        private static final byte[] nullBytes = new byte[] { 
ATypeTag.SERIALIZED_NULL_TYPE_TAG };
+    public static abstract class AbstractIfMissingOrNullEval implements 
IScalarEvaluator {
 
         private final IScalarEvaluator[] argEvals;
 
         private final IPointable argPtr;
 
-        AbstractIfEvaluator(IHyracksTaskContext ctx, IScalarEvaluatorFactory[] 
args) throws HyracksDataException {
+        AbstractIfMissingOrNullEval(IHyracksTaskContext ctx, 
IScalarEvaluatorFactory[] args)
+                throws HyracksDataException {
             argEvals = new IScalarEvaluator[args.length];
             for (int i = 0; i < argEvals.length; i++) {
                 argEvals[i] = args[i].createScalarEvaluator(ctx);
@@ -88,7 +87,7 @@ public final class IfMissingOrNullDescriptor extends 
AbstractScalarFunctionDynam
                     return;
                 }
             }
-            result.set(nullBytes, 0, nullBytes.length);
+            PointableHelper.setNull(result);
         }
 
         protected abstract boolean skip(byte argTypeTag);

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3f6d3709/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IfNanDescriptor.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IfNanDescriptor.java
 
b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IfNanDescriptor.java
new file mode 100644
index 0000000..9c1f024
--- /dev/null
+++ 
b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IfNanDescriptor.java
@@ -0,0 +1,67 @@
+/*
+ * 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 org.apache.asterix.om.functions.BuiltinFunctions;
+import org.apache.asterix.om.functions.IFunctionDescriptorFactory;
+import 
org.apache.asterix.runtime.evaluators.base.AbstractScalarFunctionDynamicDescriptor;
+import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory;
+import org.apache.hyracks.api.context.IHyracksTaskContext;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+
+public class IfNanDescriptor extends AbstractScalarFunctionDynamicDescriptor {
+
+    private static final long serialVersionUID = 1L;
+    public static final IFunctionDescriptorFactory FACTORY = 
IfNanDescriptor::new;
+
+    @Override
+    public IScalarEvaluatorFactory createEvaluatorFactory(final 
IScalarEvaluatorFactory[] args) {
+        return new IScalarEvaluatorFactory() {
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            public IScalarEvaluator createScalarEvaluator(final 
IHyracksTaskContext ctx) throws HyracksDataException {
+                return new IfNanOrInfDescriptor.AbstractIfInfOrNanEval(ctx, 
args) {
+                    @Override
+                    protected boolean skipDouble(double d) {
+                        return Double.isNaN(d);
+                    }
+
+                    @Override
+                    protected boolean skipFloat(float f) {
+                        return Float.isNaN(f);
+                    }
+
+                    @Override
+                    protected FunctionIdentifier getIdentifier() {
+                        return IfNanDescriptor.this.getIdentifier();
+                    }
+                };
+            }
+        };
+    }
+
+    @Override
+    public FunctionIdentifier getIdentifier() {
+        return BuiltinFunctions.IF_NAN;
+    }
+}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3f6d3709/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IfNanOrInfDescriptor.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IfNanOrInfDescriptor.java
 
b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IfNanOrInfDescriptor.java
new file mode 100644
index 0000000..bf61922
--- /dev/null
+++ 
b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IfNanOrInfDescriptor.java
@@ -0,0 +1,135 @@
+/*
+ * 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 org.apache.asterix.common.exceptions.ErrorCode;
+import org.apache.asterix.common.exceptions.RuntimeDataException;
+import org.apache.asterix.om.functions.BuiltinFunctions;
+import org.apache.asterix.om.functions.IFunctionDescriptorFactory;
+import org.apache.asterix.om.types.ATypeTag;
+import 
org.apache.asterix.runtime.evaluators.base.AbstractScalarFunctionDynamicDescriptor;
+import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory;
+import org.apache.hyracks.api.context.IHyracksTaskContext;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.apache.hyracks.data.std.api.IPointable;
+import org.apache.hyracks.data.std.primitive.DoublePointable;
+import org.apache.hyracks.data.std.primitive.FloatPointable;
+import org.apache.hyracks.data.std.primitive.VoidPointable;
+import org.apache.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
+
+public class IfNanOrInfDescriptor extends 
AbstractScalarFunctionDynamicDescriptor {
+
+    private static final long serialVersionUID = 1L;
+    public static final IFunctionDescriptorFactory FACTORY = 
IfNanOrInfDescriptor::new;
+
+    @Override
+    public IScalarEvaluatorFactory createEvaluatorFactory(final 
IScalarEvaluatorFactory[] args) {
+        return new IScalarEvaluatorFactory() {
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            public IScalarEvaluator createScalarEvaluator(final 
IHyracksTaskContext ctx) throws HyracksDataException {
+                return new AbstractIfInfOrNanEval(ctx, args) {
+                    @Override
+                    protected boolean skipDouble(double d) {
+                        return Double.isInfinite(d) || Double.isNaN(d);
+                    }
+
+                    @Override
+                    protected boolean skipFloat(float f) {
+                        return Float.isInfinite(f) || Float.isNaN(f);
+                    }
+
+                    @Override
+                    protected FunctionIdentifier getIdentifier() {
+                        return IfNanOrInfDescriptor.this.getIdentifier();
+                    }
+                };
+            }
+        };
+    }
+
+    @Override
+    public FunctionIdentifier getIdentifier() {
+        return BuiltinFunctions.IF_NAN_OR_INF;
+    }
+
+    public static abstract class AbstractIfInfOrNanEval implements 
IScalarEvaluator {
+
+        private final IScalarEvaluator[] argEvals;
+
+        private final IPointable argPtr;
+
+        AbstractIfInfOrNanEval(IHyracksTaskContext ctx, 
IScalarEvaluatorFactory[] args) throws HyracksDataException {
+            argEvals = new IScalarEvaluator[args.length];
+            for (int i = 0; i < argEvals.length; i++) {
+                argEvals[i] = args[i].createScalarEvaluator(ctx);
+            }
+            argPtr = new VoidPointable();
+        }
+
+        @Override
+        public void evaluate(IFrameTupleReference tuple, IPointable result) 
throws HyracksDataException {
+            for (int i = 0; i < argEvals.length; i++) {
+                argEvals[i].evaluate(tuple, argPtr);
+                ATypeTag argTypeTag = PointableHelper.getTypeTag(argPtr);
+                if (argTypeTag == null) {
+                    throw new RuntimeDataException(ErrorCode.INVALID_FORMAT, 
getIdentifier(), i);
+                }
+                switch (argTypeTag) {
+                    case DOUBLE:
+                        double d = 
DoublePointable.getDouble(argPtr.getByteArray(), argPtr.getStartOffset() + 1);
+                        if (skipDouble(d)) {
+                            continue;
+                        }
+                        result.set(argPtr);
+                        return;
+                    case FLOAT:
+                        float f = 
FloatPointable.getFloat(argPtr.getByteArray(), argPtr.getStartOffset() + 1);
+                        if (skipFloat(f)) {
+                            continue;
+                        }
+                        result.set(argPtr);
+                        return;
+                    case BIGINT:
+                    case INTEGER:
+                    case SMALLINT:
+                    case TINYINT:
+                    case MISSING:
+                        result.set(argPtr);
+                        return;
+                    default:
+                        PointableHelper.setNull(result);
+                        return;
+                }
+            }
+
+            PointableHelper.setNull(result);
+        }
+
+        protected abstract FunctionIdentifier getIdentifier();
+
+        protected abstract boolean skipDouble(double d);
+
+        protected abstract boolean skipFloat(float f);
+    }
+}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3f6d3709/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IfNullDescriptor.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IfNullDescriptor.java
 
b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IfNullDescriptor.java
index 11e464a..e5316cb 100644
--- 
a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IfNullDescriptor.java
+++ 
b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IfNullDescriptor.java
@@ -41,7 +41,7 @@ public final class IfNullDescriptor extends 
AbstractScalarFunctionDynamicDescrip
 
             @Override
             public IScalarEvaluator createScalarEvaluator(final 
IHyracksTaskContext ctx) throws HyracksDataException {
-                return new IfMissingOrNullDescriptor.AbstractIfEvaluator(ctx, 
args) {
+                return new 
IfMissingOrNullDescriptor.AbstractIfMissingOrNullEval(ctx, args) {
                     @Override
                     protected boolean skip(byte argTypeTag) {
                         return argTypeTag == ATypeTag.SERIALIZED_NULL_TYPE_TAG;

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3f6d3709/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/PointableHelper.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/PointableHelper.java
 
b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/PointableHelper.java
index df8fc75..1c69d4c 100644
--- 
a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/PointableHelper.java
+++ 
b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/PointableHelper.java
@@ -28,6 +28,7 @@ import 
org.apache.hyracks.api.dataflow.value.IBinaryComparator;
 import org.apache.hyracks.api.exceptions.HyracksDataException;
 import org.apache.hyracks.data.std.accessors.PointableBinaryComparatorFactory;
 import org.apache.hyracks.data.std.api.IMutableValueStorage;
+import org.apache.hyracks.data.std.api.IPointable;
 import org.apache.hyracks.data.std.api.IValueReference;
 import org.apache.hyracks.data.std.primitive.UTF8StringPointable;
 import org.apache.hyracks.util.string.UTF8StringWriter;
@@ -40,6 +41,9 @@ import org.apache.hyracks.util.string.UTF8StringWriter;
  */
 
 public class PointableHelper {
+
+    private static final byte[] NULL_BYTES = new byte[] { 
ATypeTag.SERIALIZED_NULL_TYPE_TAG };
+
     private static final IBinaryComparator STRING_BINARY_COMPARATOR =
             
PointableBinaryComparatorFactory.of(UTF8StringPointable.FACTORY).createBinaryComparator();
     private final UTF8StringWriter utf8Writer;
@@ -123,4 +127,8 @@ public class PointableHelper {
             throw new HyracksDataException("Could not serialize " + str);
         }
     }
+
+    public static void setNull(IPointable pointable) {
+        pointable.set(NULL_BYTES, 0, NULL_BYTES.length);
+    }
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3f6d3709/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 2f1fdcb..c47a4de 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
@@ -162,8 +162,11 @@ import 
org.apache.asterix.runtime.evaluators.functions.GetJobParameterByNameDesc
 import org.apache.asterix.runtime.evaluators.functions.GramTokensDescriptor;
 import 
org.apache.asterix.runtime.evaluators.functions.HashedGramTokensDescriptor;
 import 
org.apache.asterix.runtime.evaluators.functions.HashedWordTokensDescriptor;
+import org.apache.asterix.runtime.evaluators.functions.IfInfDescriptor;
+import org.apache.asterix.runtime.evaluators.functions.IfNanOrInfDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.IfMissingDescriptor;
 import 
org.apache.asterix.runtime.evaluators.functions.IfMissingOrNullDescriptor;
+import org.apache.asterix.runtime.evaluators.functions.IfNanDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.IfNullDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.InjectFailureDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.IsArrayDescriptor;
@@ -483,6 +486,9 @@ public final class FunctionCollection {
         fc.addGenerated(GetItemDescriptor.FACTORY);
 
         // Numeric functions
+        fc.add(IfInfDescriptor.FACTORY);
+        fc.add(IfNanDescriptor.FACTORY);
+        fc.add(IfNanOrInfDescriptor.FACTORY);
         fc.addGenerated(NumericUnaryMinusDescriptor.FACTORY);
         fc.addGenerated(NumericAddDescriptor.FACTORY);
         fc.addGenerated(NumericDivideDescriptor.FACTORY);

Reply via email to