You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@asterixdb.apache.org by ht...@apache.org on 2019/07/10 13:29:35 UTC

[asterixdb] branch master updated: [ASTERIXDB-2608] Don't use varargs when args number is known

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

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


The following commit(s) were added to refs/heads/master by this push:
     new 6812861  [ASTERIXDB-2608] Don't use varargs when args number is known
6812861 is described below

commit 681286151622930bfca044698986419238095602
Author: Hussain Towaileb <Hu...@Couchbase.com>
AuthorDate: Wed Jul 10 02:01:06 2019 +0300

    [ASTERIXDB-2608] Don't use varargs when args number is known
    
    - user model changes: no
    - storage format changes: no
    - interface changes: no
    
    Details:
    - Updated some type computers to not check the passed
    number of arguments, they're known.
    - Updated tests to not add exception list for some
    type computers, the tests are generic.
    - Functions don't check the max number of args passed,
    it's either variable or it's known.
    - Removed test cases that pass 1-2 variables and fail,
    the updated functions now can't be called unless the
    proper number of variables is passed (not varargs anymore).
    
    Change-Id: I8e10150bf48736a3b4eb845f649181cc1436cd0e
    Reviewed-on: https://asterix-gerrit.ics.uci.edu/3480
    Contrib: Jenkins <je...@fulliautomatix.ics.uci.edu>
    Integration-Tests: Jenkins <je...@fulliautomatix.ics.uci.edu>
    Tested-by: Jenkins <je...@fulliautomatix.ics.uci.edu>
    Reviewed-by: Hussain Towaileb <hu...@gmail.com>
---
 .../array_errors/array_errors.03.query.sqlpp       |   6 +-
 .../array_errors/array_errors.04.query.sqlpp       |   6 +-
 .../array_errors/array_errors.05.query.sqlpp       |   6 +-
 .../array_errors/array_errors.06.query.sqlpp       |  25 ---
 .../array_errors/array_errors.07.query.sqlpp       |  25 ---
 .../array_errors/array_errors.08.query.sqlpp       |  25 ---
 .../array_errors/array_errors.09.query.sqlpp       |  25 ---
 .../test/resources/runtimets/testsuite_sqlpp.xml   |   4 -
 .../asterix/om/functions/BuiltinFunctions.java     |  18 +-
 .../om/typecomputer/impl/AListTypeComputer.java    |  30 +--
 .../typecomputer/impl/ArrayRangeTypeComputer.java  |   8 -
 .../test/om/typecomputer/ExceptionTest.java        |  11 +-
 .../test/om/typecomputer/TypeComputerTest.java     | 116 +++-------
 .../evaluators/functions/ArrayRangeDescriptor.java | 195 -----------------
 .../evaluators/functions/ArrayRangeEvaluator.java  | 161 ++++++++++++++
 .../functions/ArrayRangeWithStepDescriptor.java    |  55 +++++
 .../functions/ArrayRangeWithoutStepDescriptor.java |  55 +++++
 .../functions/ArrayReplaceDescriptor.java          | 237 ---------------------
 .../functions/ArrayReplaceEvaluator.java           | 208 ++++++++++++++++++
 .../ArrayReplaceWithMaximumDescriptor.java         |  63 ++++++
 .../ArrayReplaceWithoutMaximumDescriptor.java      |  63 ++++++
 .../runtime/functions/FunctionCollection.java      |  12 +-
 22 files changed, 684 insertions(+), 670 deletions(-)

diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_errors/array_errors.03.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_errors/array_errors.03.query.sqlpp
index 17f9f14..d344f5d 100755
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_errors/array_errors.03.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_errors/array_errors.03.query.sqlpp
@@ -18,8 +18,8 @@
  */
 
 /*
-* Description  : Testing correct number of arguments required
-* Expected Res : Error, 2 or 3 args are required
+* Description  : Testing different input list types
+* Expected Res : Error due to processing different list types
 */
 
-select array_range(2);
\ No newline at end of file
+select array_symdiff([3,5,1], [2,1], {{3, 1}});
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_errors/array_errors.04.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_errors/array_errors.04.query.sqlpp
index 676ef92..84b335b 100755
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_errors/array_errors.04.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_errors/array_errors.04.query.sqlpp
@@ -18,8 +18,8 @@
  */
 
 /*
-* Description  : Testing correct number of arguments required
-* Expected Res : Error, 2 or 3 args are required
+* Description  : Testing different input list types
+* Expected Res : Error due to processing different list types
 */
 
-select array_range(2,6,1,4,5);
\ No newline at end of file
+select array_symdiffn([3,5,1], [2,1], {{3, 1}});
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_errors/array_errors.05.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_errors/array_errors.05.query.sqlpp
index 64092bb..97c219e 100755
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_errors/array_errors.05.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_errors/array_errors.05.query.sqlpp
@@ -18,8 +18,8 @@
  */
 
 /*
-* Description  : Testing correct number of arguments required
-* Expected Res : Error, 3 or 4 args are required
+* Description  : Testing different input list types
+* Expected Res : Error due to processing different list types
 */
 
-select array_replace([2,6],2);
\ No newline at end of file
+select array_union([3,5,1], [2,1], {{3, 1}});
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_errors/array_errors.06.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_errors/array_errors.06.query.sqlpp
deleted file mode 100755
index f237ef6..0000000
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_errors/array_errors.06.query.sqlpp
+++ /dev/null
@@ -1,25 +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.
- */
-
-/*
-* Description  : Testing correct number of arguments required
-* Expected Res : Error, 3 or 4 args are required
-*/
-
-select array_replace([2,6],2,5,1,6);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_errors/array_errors.07.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_errors/array_errors.07.query.sqlpp
deleted file mode 100755
index d344f5d..0000000
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_errors/array_errors.07.query.sqlpp
+++ /dev/null
@@ -1,25 +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.
- */
-
-/*
-* Description  : Testing different input list types
-* Expected Res : Error due to processing different list types
-*/
-
-select array_symdiff([3,5,1], [2,1], {{3, 1}});
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_errors/array_errors.08.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_errors/array_errors.08.query.sqlpp
deleted file mode 100755
index 84b335b..0000000
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_errors/array_errors.08.query.sqlpp
+++ /dev/null
@@ -1,25 +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.
- */
-
-/*
-* Description  : Testing different input list types
-* Expected Res : Error due to processing different list types
-*/
-
-select array_symdiffn([3,5,1], [2,1], {{3, 1}});
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_errors/array_errors.09.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_errors/array_errors.09.query.sqlpp
deleted file mode 100755
index 97c219e..0000000
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_errors/array_errors.09.query.sqlpp
+++ /dev/null
@@ -1,25 +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.
- */
-
-/*
-* Description  : Testing different input list types
-* Expected Res : Error due to processing different list types
-*/
-
-select array_union([3,5,1], [2,1], {{3, 1}});
\ 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 c297b58..4b6d797 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
@@ -2734,10 +2734,6 @@
         <output-dir compare="Text">array_errors</output-dir>
         <expected-error>Input contains different list types (in line 25, at column 8)</expected-error>
         <expected-error>Input contains different list types (in line 25, at column 8)</expected-error>
-        <expected-error>Invalid number of arguments for function array-range (in line 25, at column 8)</expected-error>
-        <expected-error>Invalid number of arguments for function array-range (in line 25, at column 8)</expected-error>
-        <expected-error>Invalid number of arguments for function array-replace (in line 25, at column 8)</expected-error>
-        <expected-error>Invalid number of arguments for function array-replace (in line 25, at column 8)</expected-error>
         <expected-error>Input contains different list types (in line 25, at column 8)</expected-error>
         <expected-error>Input contains different list types (in line 25, at column 8)</expected-error>
         <expected-error>Input contains different list types (in line 25, at column 8)</expected-error>
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 5e2257a..e95dfd0 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
@@ -239,12 +239,16 @@ public class BuiltinFunctions {
             new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "array-ifnull", 1);
     public static final FunctionIdentifier ARRAY_CONCAT =
             new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "array-concat", FunctionIdentifier.VARARGS);
-    public static final FunctionIdentifier ARRAY_RANGE =
-            new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "array-range", FunctionIdentifier.VARARGS);
+    public static final FunctionIdentifier ARRAY_RANGE_WITHOUT_STEP =
+            new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "array-range", 2);
+    public static final FunctionIdentifier ARRAY_RANGE_WITH_STEP =
+            new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "array-range", 3);
     public static final FunctionIdentifier ARRAY_FLATTEN =
             new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "array-flatten", 2);
-    public static final FunctionIdentifier ARRAY_REPLACE =
-            new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "array-replace", FunctionIdentifier.VARARGS);
+    public static final FunctionIdentifier ARRAY_REPLACE_WITHOUT_MAXIMUM =
+            new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "array-replace", 3);
+    public static final FunctionIdentifier ARRAY_REPLACE_WITH_MAXIMUM =
+            new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "array-replace", 4);
     public static final FunctionIdentifier ARRAY_SYMDIFF =
             new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "array-symdiff", FunctionIdentifier.VARARGS);
     public static final FunctionIdentifier ARRAY_SYMDIFFN =
@@ -2170,9 +2174,11 @@ public class BuiltinFunctions {
         addFunction(ARRAY_INTERSECT, AListMultiListArgsTypeComputer.INSTANCE, true);
         addFunction(ARRAY_IFNULL, ArrayIfNullTypeComputer.INSTANCE, true);
         addFunction(ARRAY_CONCAT, AListMultiListArgsTypeComputer.INSTANCE, true);
-        addFunction(ARRAY_RANGE, ArrayRangeTypeComputer.INSTANCE, true);
+        addFunction(ARRAY_RANGE_WITH_STEP, ArrayRangeTypeComputer.INSTANCE, true);
+        addFunction(ARRAY_RANGE_WITHOUT_STEP, ArrayRangeTypeComputer.INSTANCE, true);
         addFunction(ARRAY_FLATTEN, AListFirstTypeComputer.INSTANCE_FLATTEN, true);
-        addFunction(ARRAY_REPLACE, AListTypeComputer.INSTANCE_REPLACE, true);
+        addFunction(ARRAY_REPLACE_WITH_MAXIMUM, AListTypeComputer.INSTANCE_REPLACE, true);
+        addFunction(ARRAY_REPLACE_WITHOUT_MAXIMUM, AListTypeComputer.INSTANCE_REPLACE, true);
         addFunction(ARRAY_SYMDIFF, AListMultiListArgsTypeComputer.INSTANCE, true);
         addFunction(ARRAY_SYMDIFFN, AListMultiListArgsTypeComputer.INSTANCE, true);
         addFunction(ARRAY_STAR, OpenARecordTypeComputer.INSTANCE, true);
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/AListTypeComputer.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/AListTypeComputer.java
index 8d3824a..e6e491c 100755
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/AListTypeComputer.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/AListTypeComputer.java
@@ -34,42 +34,30 @@ import org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCa
  * Returns a list that is missable/nullable. The list type is taken from one of the input args which is the input list.
  */
 public class AListTypeComputer extends AbstractResultTypeComputer {
-    public static final AListTypeComputer INSTANCE_REMOVE = new AListTypeComputer(2, -1, false, false, true);
-    public static final AListTypeComputer INSTANCE_PUT = new AListTypeComputer(2, -1, false, true, true);
-    public static final AListTypeComputer INSTANCE_PREPEND = new AListTypeComputer(2, -1, true, true, false);
-    public static final AListTypeComputer INSTANCE_APPEND = new AListTypeComputer(2, -1, false, true, false);
-    public static final AListTypeComputer INSTANCE_INSERT = new AListTypeComputer(3, -1, false, true, false);
-    public static final AListTypeComputer INSTANCE_REPLACE = new AListTypeComputer(3, 4, false, true, false);
-    public static final AListTypeComputer INSTANCE_SLICE = new AListTypeComputer(-1, -1, false, false, true, false);
+    public static final AListTypeComputer INSTANCE_REMOVE = new AListTypeComputer(2, false, false, true);
+    public static final AListTypeComputer INSTANCE_PUT = new AListTypeComputer(2, false, true, true);
+    public static final AListTypeComputer INSTANCE_PREPEND = new AListTypeComputer(2, true, true, false);
+    public static final AListTypeComputer INSTANCE_APPEND = new AListTypeComputer(2, false, true, false);
+    public static final AListTypeComputer INSTANCE_INSERT = new AListTypeComputer(3, false, true, false);
+    public static final AListTypeComputer INSTANCE_REPLACE = new AListTypeComputer(3, false, true, false);
+    public static final AListTypeComputer INSTANCE_SLICE = new AListTypeComputer(-1, false, false, true);
 
     private final int minNumArgs;
-    private final int maxNumArgs;
     private final boolean listIsLast;
     private final boolean makeOpen;
     private final boolean nullInNullOut;
-    private final boolean isCheckArgumentsCount;
-
-    // Maintain the old constructor
-    private AListTypeComputer(int minNumArgs, int maxNumArgs, boolean listIsLast, boolean makeOpen,
-            boolean nullInNullOut) {
-        this(minNumArgs, maxNumArgs, listIsLast, makeOpen, nullInNullOut, true);
-    }
 
     // Use this constructor to skip checking the arguments count
-    private AListTypeComputer(int minNumArgs, int maxNumArgs, boolean listIsLast, boolean makeOpen,
-            boolean nullInNullOut, boolean isCheckArgumentsCount) {
+    private AListTypeComputer(int minNumArgs, boolean listIsLast, boolean makeOpen, boolean nullInNullOut) {
         this.minNumArgs = minNumArgs;
-        this.maxNumArgs = maxNumArgs;
         this.listIsLast = listIsLast;
         this.makeOpen = makeOpen;
         this.nullInNullOut = nullInNullOut;
-        this.isCheckArgumentsCount = isCheckArgumentsCount;
     }
 
     @Override
     protected IAType getResultType(ILogicalExpression expr, IAType... strippedInputTypes) throws AlgebricksException {
-        if (isCheckArgumentsCount && (strippedInputTypes.length < minNumArgs
-                || (maxNumArgs > 0 && strippedInputTypes.length > maxNumArgs))) {
+        if (minNumArgs > -1 && strippedInputTypes.length < minNumArgs) {
             String functionName = ((AbstractFunctionCallExpression) expr).getFunctionIdentifier().getName();
             throw new CompilationException(ErrorCode.COMPILATION_INVALID_NUM_OF_ARGS, expr.getSourceLocation(),
                     functionName);
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/ArrayRangeTypeComputer.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/ArrayRangeTypeComputer.java
index 4ff4cea..cfd7340 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/ArrayRangeTypeComputer.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/ArrayRangeTypeComputer.java
@@ -19,8 +19,6 @@
 
 package org.apache.asterix.om.typecomputer.impl;
 
-import org.apache.asterix.common.exceptions.CompilationException;
-import org.apache.asterix.common.exceptions.ErrorCode;
 import org.apache.asterix.om.typecomputer.base.AbstractResultTypeComputer;
 import org.apache.asterix.om.types.AOrderedListType;
 import org.apache.asterix.om.types.ATypeTag;
@@ -29,7 +27,6 @@ import org.apache.asterix.om.types.IAType;
 import org.apache.asterix.om.types.hierachy.ATypeHierarchy;
 import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
 import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
-import org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
 
 public class ArrayRangeTypeComputer extends AbstractResultTypeComputer {
 
@@ -42,11 +39,6 @@ public class ArrayRangeTypeComputer extends AbstractResultTypeComputer {
 
     @Override
     protected IAType getResultType(ILogicalExpression expr, IAType... strippedInputTypes) throws AlgebricksException {
-        if (strippedInputTypes.length != 2 && strippedInputTypes.length != 3) {
-            String functionName = ((AbstractFunctionCallExpression) expr).getFunctionIdentifier().getName();
-            throw new CompilationException(ErrorCode.COMPILATION_INVALID_NUM_OF_ARGS, expr.getSourceLocation(),
-                    functionName);
-        }
         IAType startNum = strippedInputTypes[0];
         IAType endNum = strippedInputTypes[1];
         IAType step = strippedInputTypes.length == 3 ? strippedInputTypes[2] : null;
diff --git a/asterixdb/asterix-om/src/test/java/org/apache/asterix/test/om/typecomputer/ExceptionTest.java b/asterixdb/asterix-om/src/test/java/org/apache/asterix/test/om/typecomputer/ExceptionTest.java
index d0ffdb9..95e669f 100644
--- a/asterixdb/asterix-om/src/test/java/org/apache/asterix/test/om/typecomputer/ExceptionTest.java
+++ b/asterixdb/asterix-om/src/test/java/org/apache/asterix/test/om/typecomputer/ExceptionTest.java
@@ -65,6 +65,12 @@ import org.reflections.scanners.SubTypesScanner;
  * Example:
  * 2 arguments, 40 types = 1600 combinations per type computer
  * 3 arguments, 40 types = 64000 combinations per type computer
+ *
+ * TODO There are 2 functions that expect a minimum arguments of 3, so passing them 2 arguments will cause them
+ * to return an exception, so they're really not being tested properly now. Probably need to add an exception list
+ * for such functions.
+ * Ideally, making the arguments in the test to be 3 will solve the issue, but that would push the tests to 64000 each
+ * and that takes too long and times out the test apparently.
  */
 
 @RunWith(Parameterized.class)
@@ -109,8 +115,11 @@ public class ExceptionTest {
     public void test() throws Exception {
 
         // Arguments list
-        Object[] opaqueParameters = new Object[] { BuiltinType.ANY, BuiltinType.ANY };
+        Object[] opaqueParameters = new Object[numberOfArguments];
         List<Mutable<ILogicalExpression>> argumentsList = new ArrayList<>(numberOfArguments);
+        for (int i = 0; i < numberOfArguments; i++) {
+            opaqueParameters[i] = BuiltinType.ANY;
+        }
 
         // Sets arguments for the mocked function expression.
         for (int index = 0; index < numberOfCombinations; ++index) {
diff --git a/asterixdb/asterix-om/src/test/java/org/apache/asterix/test/om/typecomputer/TypeComputerTest.java b/asterixdb/asterix-om/src/test/java/org/apache/asterix/test/om/typecomputer/TypeComputerTest.java
index 9f6724e..a857981 100644
--- a/asterixdb/asterix-om/src/test/java/org/apache/asterix/test/om/typecomputer/TypeComputerTest.java
+++ b/asterixdb/asterix-om/src/test/java/org/apache/asterix/test/om/typecomputer/TypeComputerTest.java
@@ -26,12 +26,22 @@ import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
 import org.apache.asterix.om.typecomputer.base.IResultTypeComputer;
+import org.apache.asterix.om.typecomputer.impl.BooleanOnlyTypeComputer;
+import org.apache.asterix.om.typecomputer.impl.BooleanOrMissingTypeComputer;
+import org.apache.asterix.om.typecomputer.impl.ClosedRecordConstructorResultType;
+import org.apache.asterix.om.typecomputer.impl.InjectFailureTypeComputer;
+import org.apache.asterix.om.typecomputer.impl.LocalAvgTypeComputer;
+import org.apache.asterix.om.typecomputer.impl.LocalSingleVarStatisticsTypeComputer;
+import org.apache.asterix.om.typecomputer.impl.NullableDoubleTypeComputer;
+import org.apache.asterix.om.typecomputer.impl.OpenRecordConstructorResultType;
+import org.apache.asterix.om.typecomputer.impl.RecordAddFieldsTypeComputer;
+import org.apache.asterix.om.typecomputer.impl.RecordMergeTypeComputer;
+import org.apache.asterix.om.typecomputer.impl.RecordRemoveFieldsTypeComputer;
 import org.apache.asterix.om.types.ATypeTag;
 import org.apache.asterix.om.types.AUnionType;
 import org.apache.asterix.om.types.BuiltinType;
@@ -62,11 +72,7 @@ import org.reflections.scanners.SubTypesScanner;
  *
  * Things to note:
  * - The function passes 6 "any" arguments because, as of now, no function that we have has more than 6 arguments.
- * two other lists are made (3 args and 4 args), those are needed by specific type computers for now, those should be
- * changed and then the lists can be removed from the test.
  * - Some functions have a different behavior with "any" value, those will be added to an exception list.
- * - Some functions check their arguments count, this will make passing 6 arguments fail,
- * those are added to exception list.
  */
 
 @RunWith(Parameterized.class)
@@ -74,13 +80,12 @@ public class TypeComputerTest {
 
     private static final Logger LOGGER = LogManager.getLogger();
 
+    // Number of arguments to create and pass to each type computer
+    private static final int NUM_OF_ARGS = 6;
+
     // type computers that have a different behavior when handling "any" type
     private static Set<String> differentBehaviorFunctions = new HashSet<>();
 
-    // TODO(Hussain) Remove this after the type computers have been updated
-    // type computers that check the number of arguments
-    private static HashMap<Field, List<Mutable<ILogicalExpression>>> checkArgsCountFunctions = new HashMap<>();
-
     // Test parameters
     @Parameter
     public String testName;
@@ -131,13 +136,7 @@ public class TypeComputerTest {
         IMetadataProvider metadataProvider = mock(IMetadataProvider.class);
 
         // Arguments all of type "any"
-        List<Mutable<ILogicalExpression>> threeArgs = createArgs(3, typeEnv);
-        List<Mutable<ILogicalExpression>> fourArgs = createArgs(4, typeEnv);
-        List<Mutable<ILogicalExpression>> sixArgs = createArgs(6, typeEnv);
-
-        // TODO(Hussain) Remove this after the type computers are updated
-        // Add to exception list for computers checking their arguments count
-        addComputersCheckingArgsCount(threeArgs, fourArgs);
+        List<Mutable<ILogicalExpression>> sixArgs = createArgs(typeEnv);
 
         // Mocks function identifier
         FunctionIdentifier functionIdentifier = mock(FunctionIdentifier.class);
@@ -154,7 +153,6 @@ public class TypeComputerTest {
         // Tests the return type. It should be either ANY or NULLABLE/MISSABLE.
         IResultTypeComputer instance;
         IAType resultType;
-        List<Mutable<ILogicalExpression>> args;
         Field[] fields = clazz.getFields();
 
         for (Field field : fields) {
@@ -163,17 +161,7 @@ public class TypeComputerTest {
             if (field.getType().equals(clazz)) {
                 LOGGER.log(Level.INFO, "Testing " + clazz.getSimpleName() + ": " + field.getName());
 
-                // Need to check if this is a special type computer that counts number of arguments
-                args = checkArgsCountFunctions.get(field);
-
-                // Yes, pass its specified arguments in the map
-                if (args != null) {
-                    when(functionCallExpression.getArguments()).thenReturn(args);
-                }
-                // No, pass six arguments
-                else {
-                    when(functionCallExpression.getArguments()).thenReturn(sixArgs);
-                }
+                when(functionCallExpression.getArguments()).thenReturn(sixArgs);
 
                 instance = (IResultTypeComputer) field.get(null);
                 resultType = instance.computeType(functionCallExpression, typeEnv, metadataProvider);
@@ -188,83 +176,41 @@ public class TypeComputerTest {
     }
 
     public static void prepare() {
-
         // Add to exception list for computers having a different behavior for "any" type
         addComputersBehavingDifferently();
     }
 
-    // TODO This is not a good practice, if the class name is changed, the test will fail and this needs to be updated
-    // Consider using annotation to avoid modifying the test and have a generic behavior
     /**
      * Adds the type computers that have a different behavior for "any" type.
      */
     private static void addComputersBehavingDifferently() {
-        differentBehaviorFunctions.add("InjectFailureTypeComputer");
-        differentBehaviorFunctions.add("RecordAddFieldsTypeComputer");
-        differentBehaviorFunctions.add("OpenRecordConstructorResultType");
-        differentBehaviorFunctions.add("RecordRemoveFieldsTypeComputer");
-        differentBehaviorFunctions.add("ClosedRecordConstructorResultType");
-        differentBehaviorFunctions.add("LocalAvgTypeComputer");
-        differentBehaviorFunctions.add("BooleanOnlyTypeComputer");
-        differentBehaviorFunctions.add("AMissingTypeComputer");
-        differentBehaviorFunctions.add("NullableDoubleTypeComputer");
-        differentBehaviorFunctions.add("RecordMergeTypeComputer");
-        differentBehaviorFunctions.add("BooleanOrMissingTypeComputer");
-        differentBehaviorFunctions.add("LocalSingleVarStatisticsTypeComputer");
-    }
-
-    // TODO(Hussain) Remove this after the type computers are updated
-    /**
-     * Adds the type computers that check the args count in their method body. If 6 arguments are passed to those
-     * computers, they're gonna throw an exception, so we manually specify how many arguments they should get.
-     *
-     * @throws Exception Exception
-     */
-    private static void addComputersCheckingArgsCount(List<Mutable<ILogicalExpression>> threeArgs,
-            List<Mutable<ILogicalExpression>> fourArgs) throws Exception {
-
-        // AListTypeComputer
-        Class<?> clazz = Class.forName("org.apache.asterix.om.typecomputer.impl.AListTypeComputer");
-        Field[] fields = clazz.getFields();
-
-        for (Field field : fields) {
-            if (field.getName().equalsIgnoreCase("INSTANCE_SLICE")) {
-                LOGGER.log(Level.INFO, field.getName() + " will use only 3 arguments");
-                checkArgsCountFunctions.put(field, threeArgs);
-            }
-
-            if (field.getName().equalsIgnoreCase("INSTANCE_REPLACE")) {
-                LOGGER.log(Level.INFO, field.getName() + " will use only 4 arguments");
-                checkArgsCountFunctions.put(field, fourArgs);
-            }
-        }
-
-        // ArrayRangeTypeComputer
-        clazz = Class.forName("org.apache.asterix.om.typecomputer.impl.ArrayRangeTypeComputer");
-        fields = clazz.getFields();
-
-        for (Field field : fields) {
-            if (field.getName().equalsIgnoreCase("INSTANCE")) {
-                LOGGER.log(Level.INFO, field.getName() + " will use only 3 arguments");
-                checkArgsCountFunctions.put(field, threeArgs);
-            }
-        }
+        differentBehaviorFunctions.add(InjectFailureTypeComputer.class.getSimpleName());
+        differentBehaviorFunctions.add(RecordAddFieldsTypeComputer.class.getSimpleName());
+        differentBehaviorFunctions.add(OpenRecordConstructorResultType.class.getSimpleName());
+        differentBehaviorFunctions.add(RecordRemoveFieldsTypeComputer.class.getSimpleName());
+        differentBehaviorFunctions.add(ClosedRecordConstructorResultType.class.getSimpleName());
+        differentBehaviorFunctions.add(LocalAvgTypeComputer.class.getSimpleName());
+        differentBehaviorFunctions.add(BooleanOnlyTypeComputer.class.getSimpleName());
+        //        differentBehaviorFunctions.add("AMissingTypeComputer"); // TODO What type computer is this?
+        differentBehaviorFunctions.add(NullableDoubleTypeComputer.class.getSimpleName());
+        differentBehaviorFunctions.add(RecordMergeTypeComputer.class.getSimpleName());
+        differentBehaviorFunctions.add(BooleanOrMissingTypeComputer.class.getSimpleName());
+        differentBehaviorFunctions.add(LocalSingleVarStatisticsTypeComputer.class.getSimpleName());
     }
 
     /**
      * Creates expressions matching the number passed as an argument. Variable type environment is set for all those
      * expressions to be of type "any".
      *
-     * @param numArgs number of arguments to create
+     * @param typeEnv Type environment
      * @return a list holding the created expressions
      * @throws Exception Exception
      */
-    private static List<Mutable<ILogicalExpression>> createArgs(int numArgs, IVariableTypeEnvironment typeEnv)
-            throws Exception {
+    private static List<Mutable<ILogicalExpression>> createArgs(IVariableTypeEnvironment typeEnv) throws Exception {
 
         List<Mutable<ILogicalExpression>> arguments = new ArrayList<>();
 
-        for (int i = 0; i < numArgs; ++i) {
+        for (int i = 0; i < NUM_OF_ARGS; ++i) {
             ILogicalExpression argument = mock(ILogicalExpression.class);
             arguments.add(new MutableObject<>(argument));
             when(typeEnv.getType(argument)).thenReturn(BuiltinType.ANY);
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayRangeDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayRangeDescriptor.java
deleted file mode 100755
index d0ef2d8..0000000
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayRangeDescriptor.java
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.asterix.runtime.evaluators.functions;
-
-import static org.apache.asterix.om.types.EnumDeserializer.ATYPETAGDESERIALIZER;
-
-import org.apache.asterix.builders.OrderedListBuilder;
-import org.apache.asterix.common.annotations.MissingNullInOutFunction;
-import org.apache.asterix.formats.nontagged.SerializerDeserializerProvider;
-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.typecomputer.impl.ArrayRangeTypeComputer;
-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.runtime.evaluators.base.AbstractScalarFunctionDynamicDescriptor;
-import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
-import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
-import org.apache.hyracks.algebricks.runtime.base.IEvaluatorContext;
-import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
-import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory;
-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.TaggedValuePointable;
-import org.apache.hyracks.data.std.util.ArrayBackedValueStorage;
-import org.apache.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
-
-/**
- * <pre>
- * array_range(start_num, end_num, step_num?) returns a new ordered list, list of long items or double items
- * depending on the supplied arguments. One floating-point arg will make it a list of double items. step_num is optional
- * where the default is 1. It returns an empty list for arguments like:
- * array_range(2, 20, -2), array_range(10, 3, 4) and array_range(1,6,0) where it cannot determine a proper sequence.
- *
- * It throws an error at compile time if the number of arguments < 2 or > 3
- *
- * It returns in order:
- * 1. missing, if any argument is missing.
- * 2. null, if any argument is null or they are not numeric or they are NaN +-INF.
- * 3. otherwise, a new list.
- *
- * </pre>
- */
-
-@MissingNullInOutFunction
-public class ArrayRangeDescriptor extends AbstractScalarFunctionDynamicDescriptor {
-    private static final long serialVersionUID = 1L;
-
-    public static final IFunctionDescriptorFactory FACTORY = new IFunctionDescriptorFactory() {
-        @Override
-        public IFunctionDescriptor createFunctionDescriptor() {
-            return new ArrayRangeDescriptor();
-        }
-    };
-
-    @Override
-    public FunctionIdentifier getIdentifier() {
-        return BuiltinFunctions.ARRAY_RANGE;
-    }
-
-    @Override
-    public IScalarEvaluatorFactory createEvaluatorFactory(final IScalarEvaluatorFactory[] args)
-            throws AlgebricksException {
-        return new IScalarEvaluatorFactory() {
-            private static final long serialVersionUID = 1L;
-
-            @Override
-            public IScalarEvaluator createScalarEvaluator(final IEvaluatorContext ctx) throws HyracksDataException {
-                return new ArrayRangeEval(args, ctx);
-            }
-        };
-    }
-
-    public class ArrayRangeEval implements IScalarEvaluator {
-        private final OrderedListBuilder listBuilder;
-        private final ArrayBackedValueStorage storage;
-        private final IScalarEvaluator startNumEval;
-        private final TaggedValuePointable start;
-        private final IScalarEvaluator endNumEval;
-        private final TaggedValuePointable end;
-        private final AMutableDouble aDouble;
-        private final AMutableInt64 aLong;
-        private IScalarEvaluator stepNumEval;
-        private TaggedValuePointable step;
-
-        public ArrayRangeEval(IScalarEvaluatorFactory[] args, IEvaluatorContext ctx) throws HyracksDataException {
-            storage = new ArrayBackedValueStorage();
-            start = new TaggedValuePointable();
-            end = new TaggedValuePointable();
-            startNumEval = args[0].createScalarEvaluator(ctx);
-            endNumEval = args[1].createScalarEvaluator(ctx);
-            listBuilder = new OrderedListBuilder();
-            aDouble = new AMutableDouble(0);
-            aLong = new AMutableInt64(0);
-            if (args.length == 3) {
-                stepNumEval = args[2].createScalarEvaluator(ctx);
-                step = new TaggedValuePointable();
-            }
-        }
-
-        @Override
-        public void evaluate(IFrameTupleReference tuple, IPointable result) throws HyracksDataException {
-            startNumEval.evaluate(tuple, start);
-            endNumEval.evaluate(tuple, end);
-            if (stepNumEval != null) {
-                stepNumEval.evaluate(tuple, step);
-            }
-
-            if (PointableHelper.checkAndSetMissingOrNull(result, start, end, step)) {
-                return;
-            }
-
-            String n = getIdentifier().getName();
-            ATypeTag startTag = ATYPETAGDESERIALIZER.deserialize(start.getTag());
-            ATypeTag endTag = ATYPETAGDESERIALIZER.deserialize(end.getTag());
-            ATypeTag stepTag = ATypeTag.INTEGER;
-            double stepNum = 1;
-            if (stepNumEval != null) {
-                stepNumEval.evaluate(tuple, step);
-                stepTag = ATYPETAGDESERIALIZER.deserialize(step.getTag());
-                if (!ATypeHierarchy.isCompatible(ATypeTag.DOUBLE, stepTag)) {
-                    PointableHelper.setNull(result);
-                    return;
-                }
-                stepNum = ATypeHierarchy.getDoubleValue(n, 2, step.getByteArray(), step.getStartOffset());
-            }
-
-            if (!ATypeHierarchy.isCompatible(ATypeTag.DOUBLE, startTag) || Double.isNaN(stepNum)
-                    || !ATypeHierarchy.isCompatible(ATypeTag.DOUBLE, endTag) || Double.isInfinite(stepNum)) {
-                PointableHelper.setNull(result);
-                return;
-            }
-
-            ISerializerDeserializer serde;
-            if (ATypeHierarchy.canPromote(startTag, ATypeTag.BIGINT)
-                    && ATypeHierarchy.canPromote(endTag, ATypeTag.BIGINT)
-                    && ATypeHierarchy.canPromote(stepTag, ATypeTag.BIGINT)) {
-                // all 3 numbers are whole numbers
-                serde = SerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.AINT64);
-                long startNum = ATypeHierarchy.getLongValue(n, 0, start.getByteArray(), start.getStartOffset());
-                long endNum = ATypeHierarchy.getLongValue(n, 1, end.getByteArray(), end.getStartOffset());
-                listBuilder.reset(ArrayRangeTypeComputer.LONG_LIST);
-                while ((startNum < endNum && stepNum > 0) || (startNum > endNum && stepNum < 0)) {
-                    aLong.setValue(startNum);
-                    storage.reset();
-                    serde.serialize(aLong, storage.getDataOutput());
-                    listBuilder.addItem(storage);
-                    startNum += stepNum;
-                }
-            } else {
-                // one number is a floating-point number
-                serde = SerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.ADOUBLE);
-                double startNum = ATypeHierarchy.getDoubleValue(n, 0, start.getByteArray(), start.getStartOffset());
-                double endNum = ATypeHierarchy.getDoubleValue(n, 1, end.getByteArray(), end.getStartOffset());
-                if (Double.isNaN(startNum) || Double.isInfinite(startNum) || Double.isNaN(endNum)
-                        || Double.isInfinite(endNum)) {
-                    PointableHelper.setNull(result);
-                    return;
-                }
-                listBuilder.reset(ArrayRangeTypeComputer.DOUBLE_LIST);
-                while ((startNum < endNum && stepNum > 0) || (startNum > endNum && stepNum < 0)) {
-                    aDouble.setValue(startNum);
-                    storage.reset();
-                    serde.serialize(aDouble, storage.getDataOutput());
-                    listBuilder.addItem(storage);
-                    startNum += stepNum;
-                }
-            }
-
-            storage.reset();
-            listBuilder.write(storage.getDataOutput(), true);
-            result.set(storage);
-        }
-    }
-}
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayRangeEvaluator.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayRangeEvaluator.java
new file mode 100755
index 0000000..8c81c38
--- /dev/null
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayRangeEvaluator.java
@@ -0,0 +1,161 @@
+/*
+ * 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 static org.apache.asterix.om.types.EnumDeserializer.ATYPETAGDESERIALIZER;
+
+import org.apache.asterix.builders.OrderedListBuilder;
+import org.apache.asterix.formats.nontagged.SerializerDeserializerProvider;
+import org.apache.asterix.om.base.AMutableDouble;
+import org.apache.asterix.om.base.AMutableInt64;
+import org.apache.asterix.om.typecomputer.impl.ArrayRangeTypeComputer;
+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.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+import org.apache.hyracks.algebricks.runtime.base.IEvaluatorContext;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory;
+import org.apache.hyracks.api.dataflow.value.ISerializerDeserializer;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.apache.hyracks.api.exceptions.SourceLocation;
+import org.apache.hyracks.data.std.api.IPointable;
+import org.apache.hyracks.data.std.primitive.TaggedValuePointable;
+import org.apache.hyracks.data.std.util.ArrayBackedValueStorage;
+import org.apache.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
+
+/**
+ * <pre>
+ * array_range(start_num, end_num, step_num?) returns a new ordered list, list of long items or double items
+ * depending on the supplied arguments. One floating-point arg will make it a list of double items. step_num is optional
+ * where the default is 1. It returns an empty list for arguments like:
+ * array_range(2, 20, -2), array_range(10, 3, 4) and array_range(1,6,0) where it cannot determine a proper sequence.
+ *
+ * It throws an error at compile time if the number of arguments < 2 or > 3
+ *
+ * It returns in order:
+ * 1. missing, if any argument is missing.
+ * 2. null, if any argument is null or they are not numeric or they are NaN +-INF.
+ * 3. otherwise, a new list.
+ *
+ * </pre>
+*/
+
+public class ArrayRangeEvaluator extends AbstractScalarEval {
+    private final OrderedListBuilder listBuilder;
+    private final ArrayBackedValueStorage storage;
+    private final IScalarEvaluator startNumEval;
+    private final TaggedValuePointable start;
+    private final IScalarEvaluator endNumEval;
+    private final TaggedValuePointable end;
+    private final AMutableDouble aDouble;
+    private final AMutableInt64 aLong;
+    private IScalarEvaluator stepNumEval;
+    private TaggedValuePointable step;
+
+    ArrayRangeEvaluator(IScalarEvaluatorFactory[] args, IEvaluatorContext ctx, SourceLocation sourceLocation,
+            FunctionIdentifier functionIdentifier) throws HyracksDataException {
+        super(sourceLocation, functionIdentifier);
+        storage = new ArrayBackedValueStorage();
+        start = new TaggedValuePointable();
+        end = new TaggedValuePointable();
+        startNumEval = args[0].createScalarEvaluator(ctx);
+        endNumEval = args[1].createScalarEvaluator(ctx);
+        listBuilder = new OrderedListBuilder();
+        aDouble = new AMutableDouble(0);
+        aLong = new AMutableInt64(0);
+        if (args.length == 3) {
+            stepNumEval = args[2].createScalarEvaluator(ctx);
+            step = new TaggedValuePointable();
+        }
+    }
+
+    @Override
+    public void evaluate(IFrameTupleReference tuple, IPointable result) throws HyracksDataException {
+        startNumEval.evaluate(tuple, start);
+        endNumEval.evaluate(tuple, end);
+        if (stepNumEval != null) {
+            stepNumEval.evaluate(tuple, step);
+        }
+
+        if (PointableHelper.checkAndSetMissingOrNull(result, start, end, step)) {
+            return;
+        }
+
+        String n = functionIdentifier.getName();
+        ATypeTag startTag = ATYPETAGDESERIALIZER.deserialize(start.getTag());
+        ATypeTag endTag = ATYPETAGDESERIALIZER.deserialize(end.getTag());
+        ATypeTag stepTag = ATypeTag.INTEGER;
+        double stepNum = 1;
+        if (stepNumEval != null) {
+            stepNumEval.evaluate(tuple, step);
+            stepTag = ATYPETAGDESERIALIZER.deserialize(step.getTag());
+            if (!ATypeHierarchy.isCompatible(ATypeTag.DOUBLE, stepTag)) {
+                PointableHelper.setNull(result);
+                return;
+            }
+            stepNum = ATypeHierarchy.getDoubleValue(n, 2, step.getByteArray(), step.getStartOffset());
+        }
+
+        if (!ATypeHierarchy.isCompatible(ATypeTag.DOUBLE, startTag) || Double.isNaN(stepNum)
+                || !ATypeHierarchy.isCompatible(ATypeTag.DOUBLE, endTag) || Double.isInfinite(stepNum)) {
+            PointableHelper.setNull(result);
+            return;
+        }
+
+        ISerializerDeserializer serde;
+        if (ATypeHierarchy.canPromote(startTag, ATypeTag.BIGINT) && ATypeHierarchy.canPromote(endTag, ATypeTag.BIGINT)
+                && ATypeHierarchy.canPromote(stepTag, ATypeTag.BIGINT)) {
+            // all 3 numbers are whole numbers
+            serde = SerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.AINT64);
+            long startNum = ATypeHierarchy.getLongValue(n, 0, start.getByteArray(), start.getStartOffset());
+            long endNum = ATypeHierarchy.getLongValue(n, 1, end.getByteArray(), end.getStartOffset());
+            listBuilder.reset(ArrayRangeTypeComputer.LONG_LIST);
+            while ((startNum < endNum && stepNum > 0) || (startNum > endNum && stepNum < 0)) {
+                aLong.setValue(startNum);
+                storage.reset();
+                serde.serialize(aLong, storage.getDataOutput());
+                listBuilder.addItem(storage);
+                startNum += stepNum;
+            }
+        } else {
+            // one number is a floating-point number
+            serde = SerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.ADOUBLE);
+            double startNum = ATypeHierarchy.getDoubleValue(n, 0, start.getByteArray(), start.getStartOffset());
+            double endNum = ATypeHierarchy.getDoubleValue(n, 1, end.getByteArray(), end.getStartOffset());
+            if (Double.isNaN(startNum) || Double.isInfinite(startNum) || Double.isNaN(endNum)
+                    || Double.isInfinite(endNum)) {
+                PointableHelper.setNull(result);
+                return;
+            }
+            listBuilder.reset(ArrayRangeTypeComputer.DOUBLE_LIST);
+            while ((startNum < endNum && stepNum > 0) || (startNum > endNum && stepNum < 0)) {
+                aDouble.setValue(startNum);
+                storage.reset();
+                serde.serialize(aDouble, storage.getDataOutput());
+                listBuilder.addItem(storage);
+                startNum += stepNum;
+            }
+        }
+
+        storage.reset();
+        listBuilder.write(storage.getDataOutput(), true);
+        result.set(storage);
+    }
+}
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayRangeWithStepDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayRangeWithStepDescriptor.java
new file mode 100755
index 0000000..5356bfe
--- /dev/null
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayRangeWithStepDescriptor.java
@@ -0,0 +1,55 @@
+/*
+ * 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.annotations.MissingNullInOutFunction;
+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.common.exceptions.AlgebricksException;
+import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+import org.apache.hyracks.algebricks.runtime.base.IEvaluatorContext;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+
+@MissingNullInOutFunction
+public class ArrayRangeWithStepDescriptor extends AbstractScalarFunctionDynamicDescriptor {
+    private static final long serialVersionUID = 1L;
+
+    public static final IFunctionDescriptorFactory FACTORY = ArrayRangeWithStepDescriptor::new;
+
+    @Override
+    public FunctionIdentifier getIdentifier() {
+        return BuiltinFunctions.ARRAY_RANGE_WITH_STEP;
+    }
+
+    @Override
+    public IScalarEvaluatorFactory createEvaluatorFactory(final IScalarEvaluatorFactory[] args)
+            throws AlgebricksException {
+        return new IScalarEvaluatorFactory() {
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            public IScalarEvaluator createScalarEvaluator(final IEvaluatorContext ctx) throws HyracksDataException {
+                return new ArrayRangeEvaluator(args, ctx, sourceLoc, getIdentifier());
+            }
+        };
+    }
+}
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayRangeWithoutStepDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayRangeWithoutStepDescriptor.java
new file mode 100755
index 0000000..d34097e
--- /dev/null
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayRangeWithoutStepDescriptor.java
@@ -0,0 +1,55 @@
+/*
+ * 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.annotations.MissingNullInOutFunction;
+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.common.exceptions.AlgebricksException;
+import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+import org.apache.hyracks.algebricks.runtime.base.IEvaluatorContext;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+
+@MissingNullInOutFunction
+public class ArrayRangeWithoutStepDescriptor extends AbstractScalarFunctionDynamicDescriptor {
+    private static final long serialVersionUID = 1L;
+
+    public static final IFunctionDescriptorFactory FACTORY = ArrayRangeWithoutStepDescriptor::new;
+
+    @Override
+    public FunctionIdentifier getIdentifier() {
+        return BuiltinFunctions.ARRAY_RANGE_WITHOUT_STEP;
+    }
+
+    @Override
+    public IScalarEvaluatorFactory createEvaluatorFactory(final IScalarEvaluatorFactory[] args)
+            throws AlgebricksException {
+        return new IScalarEvaluatorFactory() {
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            public IScalarEvaluator createScalarEvaluator(final IEvaluatorContext ctx) throws HyracksDataException {
+                return new ArrayRangeEvaluator(args, ctx, sourceLoc, getIdentifier());
+            }
+        };
+    }
+}
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayReplaceDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayReplaceDescriptor.java
deleted file mode 100644
index e850476..0000000
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayReplaceDescriptor.java
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.asterix.runtime.evaluators.functions;
-
-import static org.apache.asterix.om.types.EnumDeserializer.ATYPETAGDESERIALIZER;
-
-import java.io.IOException;
-
-import org.apache.asterix.builders.IAsterixListBuilder;
-import org.apache.asterix.builders.OrderedListBuilder;
-import org.apache.asterix.builders.UnorderedListBuilder;
-import org.apache.asterix.formats.nontagged.BinaryComparatorFactoryProvider;
-import org.apache.asterix.om.functions.BuiltinFunctions;
-import org.apache.asterix.om.functions.IFunctionDescriptorFactory;
-import org.apache.asterix.om.pointables.base.DefaultOpenFieldType;
-import org.apache.asterix.om.types.ATypeTag;
-import org.apache.asterix.om.types.AbstractCollectionType;
-import org.apache.asterix.om.types.BuiltinType;
-import org.apache.asterix.om.types.IAType;
-import org.apache.asterix.om.types.hierachy.ATypeHierarchy;
-import org.apache.asterix.runtime.evaluators.base.AbstractScalarFunctionDynamicDescriptor;
-import org.apache.asterix.runtime.evaluators.common.ListAccessor;
-import org.apache.asterix.runtime.functions.FunctionTypeInferers;
-import org.apache.asterix.runtime.utils.DescriptorFactoryUtil;
-import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
-import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
-import org.apache.hyracks.algebricks.runtime.base.IEvaluatorContext;
-import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
-import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory;
-import org.apache.hyracks.api.dataflow.value.IBinaryComparator;
-import org.apache.hyracks.api.exceptions.HyracksDataException;
-import org.apache.hyracks.data.std.api.AbstractPointable;
-import org.apache.hyracks.data.std.api.IPointable;
-import org.apache.hyracks.data.std.primitive.TaggedValuePointable;
-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;
-
-/**
- * <pre>
- * array_replace(list, val1, val2, max_num_times?) returns a new list with the occurrences of val1 replaced with
- * val2. max_num_times arg is optional. If supplied, it replaces val1 as many as max_num_times. Any negative number for
- * max_num_times means "replace all occurrences". val2 can be null meaning you can replace existing items with nulls.
- *
- * array_replace([2,3,3,3,1], 3, 8, 0) will do nothing and result in [2,3,3,3,1].
- *
- * It throws an error at compile time if the number of arguments < 3 or > 4
- *
- * It returns (or throws an error at runtime) in order:
- * 1. missing, if any argument is missing.
- * 2. null, if:
- * - any argument is null (except for val2).
- * - input list is not a list.
- * - num_times is not numeric or it's a floating-point number with decimals, e.g, 3.2 (3.0 is OK).
- * 3. otherwise, a new list.
- *
- * </pre>
- */
-public class ArrayReplaceDescriptor extends AbstractScalarFunctionDynamicDescriptor {
-    private static final long serialVersionUID = 1L;
-    private IAType inputListType;
-    private IAType targetValueType;
-    private IAType newValueType;
-
-    public static final IFunctionDescriptorFactory FACTORY =
-            DescriptorFactoryUtil.createFactory(ArrayReplaceDescriptor::new, FunctionTypeInferers.SET_ARGUMENTS_TYPE);
-
-    @Override
-    public FunctionIdentifier getIdentifier() {
-        return BuiltinFunctions.ARRAY_REPLACE;
-    }
-
-    @Override
-    public void setImmutableStates(Object... states) {
-        inputListType = (IAType) states[0];
-        targetValueType = (IAType) states[1];
-        newValueType = (IAType) states[2];
-    }
-
-    @Override
-    public IScalarEvaluatorFactory createEvaluatorFactory(final IScalarEvaluatorFactory[] args)
-            throws AlgebricksException {
-        return new IScalarEvaluatorFactory() {
-            private static final long serialVersionUID = 1L;
-
-            @Override
-            public IScalarEvaluator createScalarEvaluator(final IEvaluatorContext ctx) throws HyracksDataException {
-                return new ArrayReplaceEval(args, ctx);
-            }
-        };
-    }
-
-    public class ArrayReplaceEval implements IScalarEvaluator {
-        private final IScalarEvaluator listEval;
-        private final IScalarEvaluator targetValEval;
-        private final IScalarEvaluator newValEval;
-        private IScalarEvaluator maxEval;
-        private final IPointable list;
-        private final IPointable tempList;
-        private final IPointable target;
-        private final IPointable newVal;
-        private final IPointable tempVal;
-        private TaggedValuePointable maxArg;
-        private final AbstractPointable item;
-        private final ListAccessor listAccessor;
-        private final IBinaryComparator comp;
-        private final ArrayBackedValueStorage storage;
-        private final CastTypeEvaluator caster;
-        private IAsterixListBuilder orderedListBuilder;
-        private IAsterixListBuilder unorderedListBuilder;
-
-        ArrayReplaceEval(IScalarEvaluatorFactory[] args, IEvaluatorContext ctx) throws HyracksDataException {
-            storage = new ArrayBackedValueStorage();
-            listEval = args[0].createScalarEvaluator(ctx);
-            targetValEval = args[1].createScalarEvaluator(ctx);
-            newValEval = args[2].createScalarEvaluator(ctx);
-            if (args.length == 4) {
-                maxEval = args[3].createScalarEvaluator(ctx);
-                maxArg = new TaggedValuePointable();
-            }
-            list = new VoidPointable();
-            tempList = new VoidPointable();
-            target = new VoidPointable();
-            newVal = new VoidPointable();
-            tempVal = new VoidPointable();
-            item = new VoidPointable();
-            listAccessor = new ListAccessor();
-            caster = new CastTypeEvaluator();
-            orderedListBuilder = null;
-            unorderedListBuilder = null;
-            // the input list will be opened, therefore, the type of left (item type) is ANY
-            comp = BinaryComparatorFactoryProvider.INSTANCE
-                    .getBinaryComparatorFactory(BuiltinType.ANY, targetValueType, true).createBinaryComparator();
-        }
-
-        @Override
-        public void evaluate(IFrameTupleReference tuple, IPointable result) throws HyracksDataException {
-            storage.reset();
-            listEval.evaluate(tuple, tempList);
-            targetValEval.evaluate(tuple, target);
-            newValEval.evaluate(tuple, tempVal);
-            ATypeTag listType = ATYPETAGDESERIALIZER.deserialize(tempList.getByteArray()[tempList.getStartOffset()]);
-            ATypeTag targetTag = ATYPETAGDESERIALIZER.deserialize(target.getByteArray()[target.getStartOffset()]);
-            ATypeTag newValTag = ATYPETAGDESERIALIZER.deserialize(tempVal.getByteArray()[tempVal.getStartOffset()]);
-            if (listType == ATypeTag.MISSING || targetTag == ATypeTag.MISSING || newValTag == ATypeTag.MISSING) {
-                PointableHelper.setMissing(result);
-                return;
-            }
-
-            double maxDouble = -1;
-            String name = getIdentifier().getName();
-            if (maxEval != null) {
-                maxEval.evaluate(tuple, maxArg);
-                ATypeTag maxTag = ATYPETAGDESERIALIZER.deserialize(maxArg.getTag());
-                if (maxTag == ATypeTag.MISSING) {
-                    PointableHelper.setMissing(result);
-                    return;
-                } else if (!ATypeHierarchy.isCompatible(maxTag, ATypeTag.DOUBLE)) {
-                    PointableHelper.setNull(result);
-                    return;
-                }
-                maxDouble = ATypeHierarchy.getDoubleValue(name, 3, maxArg.getByteArray(), maxArg.getStartOffset());
-            }
-
-            if (!listType.isListType() || Math.floor(maxDouble) < maxDouble || targetTag == ATypeTag.NULL
-                    || Double.isInfinite(maxDouble) || Double.isNaN(maxDouble)) {
-                PointableHelper.setNull(result);
-                return;
-            }
-            try {
-                IAType defaultOpenType = DefaultOpenFieldType.getDefaultOpenFieldType(listType);
-                caster.resetAndAllocate(defaultOpenType, inputListType, listEval);
-                caster.cast(tempList, list);
-                defaultOpenType = DefaultOpenFieldType.getDefaultOpenFieldType(newValTag);
-                if (defaultOpenType != null) {
-                    caster.resetAndAllocate(defaultOpenType, newValueType, newValEval);
-                    caster.cast(tempVal, newVal);
-                } else {
-                    newVal.set(tempVal);
-                }
-                int max = (int) maxDouble;
-                // create list
-                IAsterixListBuilder listBuilder;
-                if (listType == ATypeTag.ARRAY) {
-                    if (orderedListBuilder == null) {
-                        orderedListBuilder = new OrderedListBuilder();
-                    }
-                    listBuilder = orderedListBuilder;
-                } else {
-                    if (unorderedListBuilder == null) {
-                        unorderedListBuilder = new UnorderedListBuilder();
-                    }
-                    listBuilder = unorderedListBuilder;
-                }
-                listBuilder.reset((AbstractCollectionType) DefaultOpenFieldType.getDefaultOpenFieldType(listType));
-                listAccessor.reset(list.getByteArray(), list.getStartOffset());
-                int counter = 0;
-                byte[] targetBytes = target.getByteArray();
-                int offset = target.getStartOffset();
-                int length = target.getLength();
-                for (int i = 0; i < listAccessor.size(); i++) {
-                    listAccessor.getOrWriteItem(i, item, storage);
-                    if (counter != max && comp.compare(item.getByteArray(), item.getStartOffset(), item.getLength(),
-                            targetBytes, offset, length) == 0) {
-                        listBuilder.addItem(newVal);
-                        counter++;
-                    } else {
-                        listBuilder.addItem(item);
-                    }
-                }
-                storage.reset();
-                listBuilder.write(storage.getDataOutput(), true);
-                result.set(storage);
-            } catch (IOException e) {
-                throw HyracksDataException.create(e);
-            } finally {
-                caster.deallocatePointables();
-            }
-        }
-    }
-}
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayReplaceEvaluator.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayReplaceEvaluator.java
new file mode 100644
index 0000000..63e3192
--- /dev/null
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayReplaceEvaluator.java
@@ -0,0 +1,208 @@
+/*
+* 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 static org.apache.asterix.om.types.EnumDeserializer.ATYPETAGDESERIALIZER;
+
+import java.io.IOException;
+
+import org.apache.asterix.builders.IAsterixListBuilder;
+import org.apache.asterix.builders.OrderedListBuilder;
+import org.apache.asterix.builders.UnorderedListBuilder;
+import org.apache.asterix.formats.nontagged.BinaryComparatorFactoryProvider;
+import org.apache.asterix.om.pointables.base.DefaultOpenFieldType;
+import org.apache.asterix.om.types.ATypeTag;
+import org.apache.asterix.om.types.AbstractCollectionType;
+import org.apache.asterix.om.types.BuiltinType;
+import org.apache.asterix.om.types.IAType;
+import org.apache.asterix.om.types.hierachy.ATypeHierarchy;
+import org.apache.asterix.runtime.evaluators.common.ListAccessor;
+import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+import org.apache.hyracks.algebricks.runtime.base.IEvaluatorContext;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory;
+import org.apache.hyracks.api.dataflow.value.IBinaryComparator;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.apache.hyracks.api.exceptions.SourceLocation;
+import org.apache.hyracks.data.std.api.AbstractPointable;
+import org.apache.hyracks.data.std.api.IPointable;
+import org.apache.hyracks.data.std.primitive.TaggedValuePointable;
+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;
+
+/**
+* <pre>
+* array_replace(list, val1, val2, max_num_times?) returns a new list with the occurrences of val1 replaced with
+* val2. max_num_times arg is optional. If supplied, it replaces val1 as many as max_num_times. Any negative number for
+* max_num_times means "replace all occurrences". val2 can be null meaning you can replace existing items with nulls.
+*
+* array_replace([2,3,3,3,1], 3, 8, 0) will do nothing and result in [2,3,3,3,1].
+*
+* It throws an error at compile time if the number of arguments < 3 or > 4
+*
+* It returns (or throws an error at runtime) in order:
+* 1. missing, if any argument is missing.
+* 2. null, if:
+* - any argument is null (except for val2).
+* - input list is not a list.
+* - num_times is not numeric or it's a floating-point number with decimals, e.g, 3.2 (3.0 is OK).
+* 3. otherwise, a new list.
+*
+* </pre>
+*/
+
+public class ArrayReplaceEvaluator extends AbstractScalarEval {
+
+    private final IAType inputListType;
+    private final IAType newValueType;
+    private final IScalarEvaluator listEval;
+    private final IScalarEvaluator targetValEval;
+    private final IScalarEvaluator newValEval;
+    private IScalarEvaluator maxEval;
+    private final IPointable list;
+    private final IPointable tempList;
+    private final IPointable target;
+    private final IPointable newVal;
+    private final IPointable tempVal;
+    private TaggedValuePointable maxArg;
+    private final AbstractPointable item;
+    private final ListAccessor listAccessor;
+    private final IBinaryComparator comp;
+    private final ArrayBackedValueStorage storage;
+    private final CastTypeEvaluator caster;
+    private IAsterixListBuilder orderedListBuilder;
+    private IAsterixListBuilder unorderedListBuilder;
+
+    ArrayReplaceEvaluator(IScalarEvaluatorFactory[] args, IEvaluatorContext ctx, SourceLocation sourceLocation,
+            FunctionIdentifier functionIdentifier, IAType[] argTypes) throws HyracksDataException {
+        super(sourceLocation, functionIdentifier);
+        storage = new ArrayBackedValueStorage();
+        listEval = args[0].createScalarEvaluator(ctx);
+        targetValEval = args[1].createScalarEvaluator(ctx);
+        newValEval = args[2].createScalarEvaluator(ctx);
+        if (args.length == 4) {
+            maxEval = args[3].createScalarEvaluator(ctx);
+            maxArg = new TaggedValuePointable();
+        }
+        list = new VoidPointable();
+        tempList = new VoidPointable();
+        target = new VoidPointable();
+        newVal = new VoidPointable();
+        tempVal = new VoidPointable();
+        item = new VoidPointable();
+        listAccessor = new ListAccessor();
+        caster = new CastTypeEvaluator();
+        orderedListBuilder = null;
+        unorderedListBuilder = null;
+
+        inputListType = argTypes[0];
+        IAType targetValueType = argTypes[1];
+        newValueType = argTypes[2];
+
+        // the input list will be opened, therefore, the type of left (item type) is ANY
+        comp = BinaryComparatorFactoryProvider.INSTANCE
+                .getBinaryComparatorFactory(BuiltinType.ANY, targetValueType, true).createBinaryComparator();
+    }
+
+    @Override
+    public void evaluate(IFrameTupleReference tuple, IPointable result) throws HyracksDataException {
+        storage.reset();
+        listEval.evaluate(tuple, tempList);
+        targetValEval.evaluate(tuple, target);
+        newValEval.evaluate(tuple, tempVal);
+        ATypeTag listType = ATYPETAGDESERIALIZER.deserialize(tempList.getByteArray()[tempList.getStartOffset()]);
+        ATypeTag targetTag = ATYPETAGDESERIALIZER.deserialize(target.getByteArray()[target.getStartOffset()]);
+        ATypeTag newValTag = ATYPETAGDESERIALIZER.deserialize(tempVal.getByteArray()[tempVal.getStartOffset()]);
+        if (listType == ATypeTag.MISSING || targetTag == ATypeTag.MISSING || newValTag == ATypeTag.MISSING) {
+            PointableHelper.setMissing(result);
+            return;
+        }
+
+        double maxDouble = -1;
+        String name = functionIdentifier.getName();
+        if (maxEval != null) {
+            maxEval.evaluate(tuple, maxArg);
+            ATypeTag maxTag = ATYPETAGDESERIALIZER.deserialize(maxArg.getTag());
+            if (maxTag == ATypeTag.MISSING) {
+                PointableHelper.setMissing(result);
+                return;
+            } else if (!ATypeHierarchy.isCompatible(maxTag, ATypeTag.DOUBLE)) {
+                PointableHelper.setNull(result);
+                return;
+            }
+            maxDouble = ATypeHierarchy.getDoubleValue(name, 3, maxArg.getByteArray(), maxArg.getStartOffset());
+        }
+
+        if (!listType.isListType() || Math.floor(maxDouble) < maxDouble || targetTag == ATypeTag.NULL
+                || Double.isInfinite(maxDouble) || Double.isNaN(maxDouble)) {
+            PointableHelper.setNull(result);
+            return;
+        }
+        try {
+            IAType defaultOpenType = DefaultOpenFieldType.getDefaultOpenFieldType(listType);
+            caster.resetAndAllocate(defaultOpenType, inputListType, listEval);
+            caster.cast(tempList, list);
+            defaultOpenType = DefaultOpenFieldType.getDefaultOpenFieldType(newValTag);
+            if (defaultOpenType != null) {
+                caster.resetAndAllocate(defaultOpenType, newValueType, newValEval);
+                caster.cast(tempVal, newVal);
+            } else {
+                newVal.set(tempVal);
+            }
+            int max = (int) maxDouble;
+            // create list
+            IAsterixListBuilder listBuilder;
+            if (listType == ATypeTag.ARRAY) {
+                if (orderedListBuilder == null) {
+                    orderedListBuilder = new OrderedListBuilder();
+                }
+                listBuilder = orderedListBuilder;
+            } else {
+                if (unorderedListBuilder == null) {
+                    unorderedListBuilder = new UnorderedListBuilder();
+                }
+                listBuilder = unorderedListBuilder;
+            }
+            listBuilder.reset((AbstractCollectionType) DefaultOpenFieldType.getDefaultOpenFieldType(listType));
+            listAccessor.reset(list.getByteArray(), list.getStartOffset());
+            int counter = 0;
+            byte[] targetBytes = target.getByteArray();
+            int offset = target.getStartOffset();
+            int length = target.getLength();
+            for (int i = 0; i < listAccessor.size(); i++) {
+                listAccessor.getOrWriteItem(i, item, storage);
+                if (counter != max && comp.compare(item.getByteArray(), item.getStartOffset(), item.getLength(),
+                        targetBytes, offset, length) == 0) {
+                    listBuilder.addItem(newVal);
+                    counter++;
+                } else {
+                    listBuilder.addItem(item);
+                }
+            }
+            storage.reset();
+            listBuilder.write(storage.getDataOutput(), true);
+            result.set(storage);
+        } catch (IOException e) {
+            throw HyracksDataException.create(e);
+        } finally {
+            caster.deallocatePointables();
+        }
+    }
+}
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayReplaceWithMaximumDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayReplaceWithMaximumDescriptor.java
new file mode 100644
index 0000000..36e3250
--- /dev/null
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayReplaceWithMaximumDescriptor.java
@@ -0,0 +1,63 @@
+/*
+ * 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.om.types.IAType;
+import org.apache.asterix.runtime.evaluators.base.AbstractScalarFunctionDynamicDescriptor;
+import org.apache.asterix.runtime.functions.FunctionTypeInferers;
+import org.apache.asterix.runtime.utils.DescriptorFactoryUtil;
+import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
+import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+import org.apache.hyracks.algebricks.runtime.base.IEvaluatorContext;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+
+public class ArrayReplaceWithMaximumDescriptor extends AbstractScalarFunctionDynamicDescriptor {
+    private static final long serialVersionUID = 1L;
+    public static final IFunctionDescriptorFactory FACTORY = DescriptorFactoryUtil
+            .createFactory(ArrayReplaceWithMaximumDescriptor::new, FunctionTypeInferers.SET_ARGUMENTS_TYPE);
+
+    private IAType[] argTypes;
+
+    @Override
+    public FunctionIdentifier getIdentifier() {
+        return BuiltinFunctions.ARRAY_REPLACE_WITH_MAXIMUM;
+    }
+
+    @Override
+    public void setImmutableStates(Object... states) {
+        argTypes = (IAType[]) states;
+    }
+
+    @Override
+    public IScalarEvaluatorFactory createEvaluatorFactory(final IScalarEvaluatorFactory[] args)
+            throws AlgebricksException {
+        return new IScalarEvaluatorFactory() {
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            public IScalarEvaluator createScalarEvaluator(final IEvaluatorContext ctx) throws HyracksDataException {
+                return new ArrayReplaceEvaluator(args, ctx, sourceLoc, getIdentifier(), argTypes);
+            }
+        };
+    }
+}
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayReplaceWithoutMaximumDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayReplaceWithoutMaximumDescriptor.java
new file mode 100644
index 0000000..6011225
--- /dev/null
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayReplaceWithoutMaximumDescriptor.java
@@ -0,0 +1,63 @@
+/*
+ * 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.om.types.IAType;
+import org.apache.asterix.runtime.evaluators.base.AbstractScalarFunctionDynamicDescriptor;
+import org.apache.asterix.runtime.functions.FunctionTypeInferers;
+import org.apache.asterix.runtime.utils.DescriptorFactoryUtil;
+import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
+import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+import org.apache.hyracks.algebricks.runtime.base.IEvaluatorContext;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+
+public class ArrayReplaceWithoutMaximumDescriptor extends AbstractScalarFunctionDynamicDescriptor {
+    private static final long serialVersionUID = 1L;
+    public static final IFunctionDescriptorFactory FACTORY = DescriptorFactoryUtil
+            .createFactory(ArrayReplaceWithoutMaximumDescriptor::new, FunctionTypeInferers.SET_ARGUMENTS_TYPE);
+
+    private IAType[] argTypes;
+
+    @Override
+    public FunctionIdentifier getIdentifier() {
+        return BuiltinFunctions.ARRAY_REPLACE_WITHOUT_MAXIMUM;
+    }
+
+    @Override
+    public void setImmutableStates(Object... states) {
+        argTypes = (IAType[]) states;
+    }
+
+    @Override
+    public IScalarEvaluatorFactory createEvaluatorFactory(final IScalarEvaluatorFactory[] args)
+            throws AlgebricksException {
+        return new IScalarEvaluatorFactory() {
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            public IScalarEvaluator createScalarEvaluator(final IEvaluatorContext ctx) throws HyracksDataException {
+                return new ArrayReplaceEvaluator(args, ctx, sourceLoc, getIdentifier(), argTypes);
+            }
+        };
+    }
+}
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 b5b2097..1fa9462 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
@@ -304,10 +304,12 @@ import org.apache.asterix.runtime.evaluators.functions.ArrayIntersectDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.ArrayPositionDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.ArrayPrependDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.ArrayPutDescriptor;
-import org.apache.asterix.runtime.evaluators.functions.ArrayRangeDescriptor;
+import org.apache.asterix.runtime.evaluators.functions.ArrayRangeWithStepDescriptor;
+import org.apache.asterix.runtime.evaluators.functions.ArrayRangeWithoutStepDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.ArrayRemoveDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.ArrayRepeatDescriptor;
-import org.apache.asterix.runtime.evaluators.functions.ArrayReplaceDescriptor;
+import org.apache.asterix.runtime.evaluators.functions.ArrayReplaceWithMaximumDescriptor;
+import org.apache.asterix.runtime.evaluators.functions.ArrayReplaceWithoutMaximumDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.ArrayReverseDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.ArraySliceWithEndPositionDescriptor;
 import org.apache.asterix.runtime.evaluators.functions.ArraySliceWithoutEndPositionDescriptor;
@@ -580,9 +582,11 @@ public final class FunctionCollection implements IFunctionCollection {
         fc.add(ArrayIntersectDescriptor.FACTORY);
         fc.add(ArrayIfNullDescriptor.FACTORY);
         fc.add(ArrayConcatDescriptor.FACTORY);
-        fc.add(ArrayRangeDescriptor.FACTORY);
+        fc.add(ArrayRangeWithStepDescriptor.FACTORY);
+        fc.add(ArrayRangeWithoutStepDescriptor.FACTORY);
         fc.add(ArrayFlattenDescriptor.FACTORY);
-        fc.add(ArrayReplaceDescriptor.FACTORY);
+        fc.add(ArrayReplaceWithMaximumDescriptor.FACTORY);
+        fc.add(ArrayReplaceWithoutMaximumDescriptor.FACTORY);
         fc.add(ArraySliceWithEndPositionDescriptor.FACTORY);
         fc.add(ArraySliceWithoutEndPositionDescriptor.FACTORY);
         fc.add(ArraySymDiffDescriptor.FACTORY);