[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 <jenkins@fulliautomatix.ics.uci.edu>
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Hussain Towaileb <hussainht@gmail.com>
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 @@
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 @@
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 @@
* 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 4ff4cea5..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.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 @@
@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 @@
* 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 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.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 @@
*
* 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 @@
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 @@
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 @@
// 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 @@
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 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.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 @@
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);