This is an automated email from the ASF dual-hosted git repository.
jiajunxie pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/calcite.git
The following commit(s) were added to refs/heads/main by this push:
new baa6b104f3 [CALCITE-5710] Add ARRAY_MAX, ARRAY_MIN function (enabled
in Spark library)
baa6b104f3 is described below
commit baa6b104f33a851e419bd95e18acf3766aa19838
Author: yongen.ly <[email protected]>
AuthorDate: Thu May 18 16:51:44 2023 +0800
[CALCITE-5710] Add ARRAY_MAX, ARRAY_MIN function (enabled in Spark library)
---
.../calcite/adapter/enumerable/RexImpTable.java | 4 +++
.../org/apache/calcite/runtime/SqlFunctions.java | 28 +++++++++++++++++++
.../main/java/org/apache/calcite/sql/SqlKind.java | 6 +++++
.../calcite/sql/fun/SqlLibraryOperators.java | 14 ++++++++++
.../org/apache/calcite/sql/type/ReturnTypes.java | 17 +++++++++++-
.../apache/calcite/sql/type/SqlTypeTransforms.java | 5 ++--
.../org/apache/calcite/util/BuiltInMethod.java | 2 ++
site/_docs/reference.md | 2 ++
.../org/apache/calcite/test/SqlOperatorTest.java | 31 ++++++++++++++++++++++
9 files changed, 106 insertions(+), 3 deletions(-)
diff --git
a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
index 925bbec92e..cad65ffa60 100644
--- a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
+++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
@@ -123,6 +123,8 @@ import static
org.apache.calcite.sql.fun.SqlLibraryOperators.ARRAY_CONCAT;
import static org.apache.calcite.sql.fun.SqlLibraryOperators.ARRAY_CONCAT_AGG;
import static org.apache.calcite.sql.fun.SqlLibraryOperators.ARRAY_DISTINCT;
import static org.apache.calcite.sql.fun.SqlLibraryOperators.ARRAY_LENGTH;
+import static org.apache.calcite.sql.fun.SqlLibraryOperators.ARRAY_MAX;
+import static org.apache.calcite.sql.fun.SqlLibraryOperators.ARRAY_MIN;
import static org.apache.calcite.sql.fun.SqlLibraryOperators.ARRAY_REPEAT;
import static org.apache.calcite.sql.fun.SqlLibraryOperators.ARRAY_REVERSE;
import static org.apache.calcite.sql.fun.SqlLibraryOperators.ARRAY_SIZE;
@@ -691,6 +693,8 @@ public class RexImpTable {
defineMethod(MEMBER_OF, BuiltInMethod.MEMBER_OF.method, NullPolicy.NONE);
defineMethod(ARRAY_COMPACT, BuiltInMethod.ARRAY_COMPACT.method,
NullPolicy.STRICT);
defineMethod(ARRAY_DISTINCT, BuiltInMethod.ARRAY_DISTINCT.method,
NullPolicy.STRICT);
+ defineMethod(ARRAY_MAX, BuiltInMethod.ARRAY_MAX.method,
NullPolicy.STRICT);
+ defineMethod(ARRAY_MIN, BuiltInMethod.ARRAY_MIN.method,
NullPolicy.STRICT);
defineMethod(ARRAY_REPEAT, BuiltInMethod.ARRAY_REPEAT.method,
NullPolicy.NONE);
defineMethod(ARRAY_REVERSE, BuiltInMethod.ARRAY_REVERSE.method,
NullPolicy.STRICT);
defineMethod(ARRAY_SIZE, BuiltInMethod.COLLECTION_SIZE.method,
NullPolicy.STRICT);
diff --git a/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
b/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
index 8c68768d1b..0db3921cca 100644
--- a/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
+++ b/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
@@ -3886,6 +3886,34 @@ public class SqlFunctions {
return new ArrayList<>(result);
}
+ /** Support the ARRAY_MAX function. */
+ public static @Nullable <T extends Object & Comparable<? super T>> T
arrayMax(
+ List<? extends T> list) {
+
+ T max = null;
+ for (int i = 0; i < list.size(); i++) {
+ T item = list.get(i);
+ if (item != null && (max == null || item.compareTo(max) > 0)) {
+ max = item;
+ }
+ }
+ return max;
+ }
+
+ /** Support the ARRAY_MIN function. */
+ public static @Nullable <T extends Object & Comparable<? super T>> T
arrayMin(
+ List<? extends T> list) {
+
+ T min = null;
+ for (int i = 0; i < list.size(); i++) {
+ T item = list.get(i);
+ if (item != null && (min == null || item.compareTo(min) < 0)) {
+ min = item;
+ }
+ }
+ return min;
+ }
+
/** Support the ARRAY_REPEAT function. */
public static @Nullable List<Object> repeat(Object element, Object count) {
if (count == null) {
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlKind.java
b/core/src/main/java/org/apache/calcite/sql/SqlKind.java
index b1f18b7136..7c2c698e1d 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlKind.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlKind.java
@@ -686,6 +686,12 @@ public enum SqlKind {
/** {@code ARRAY_DISTINCT} function (Spark semantics). */
ARRAY_DISTINCT,
+ /** {@code ARRAY_MAX} function (Spark semantics). */
+ ARRAY_MAX,
+
+ /** {@code ARRAY_MIN} function (Spark semantics). */
+ ARRAY_MIN,
+
/** {@code ARRAY_REPEAT} function (Spark semantics). */
ARRAY_REPEAT,
diff --git
a/core/src/main/java/org/apache/calcite/sql/fun/SqlLibraryOperators.java
b/core/src/main/java/org/apache/calcite/sql/fun/SqlLibraryOperators.java
index bcc6e3fa1f..ec0627a89b 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlLibraryOperators.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlLibraryOperators.java
@@ -886,6 +886,20 @@ public abstract class SqlLibraryOperators {
ReturnTypes.INTEGER_NULLABLE,
OperandTypes.ARRAY);
+ /** The "ARRAY_MAX(array)" function. */
+ @LibraryOperator(libraries = {SPARK})
+ public static final SqlFunction ARRAY_MAX =
+ SqlBasicFunction.create(SqlKind.ARRAY_MAX,
+ ReturnTypes.TO_COLLECTION_ELEMENT_FORCE_NULLABLE,
+ OperandTypes.ARRAY);
+
+ /** The "ARRAY_MAX(array)" function. */
+ @LibraryOperator(libraries = {SPARK})
+ public static final SqlFunction ARRAY_MIN =
+ SqlBasicFunction.create(SqlKind.ARRAY_MIN,
+ ReturnTypes.TO_COLLECTION_ELEMENT_FORCE_NULLABLE,
+ OperandTypes.ARRAY);
+
/** The "ARRAY_REPEAT(element, count)" function. */
@LibraryOperator(libraries = {SPARK})
public static final SqlFunction ARRAY_REPEAT =
diff --git a/core/src/main/java/org/apache/calcite/sql/type/ReturnTypes.java
b/core/src/main/java/org/apache/calcite/sql/type/ReturnTypes.java
index adf1ca3902..8fdab7ea51 100644
--- a/core/src/main/java/org/apache/calcite/sql/type/ReturnTypes.java
+++ b/core/src/main/java/org/apache/calcite/sql/type/ReturnTypes.java
@@ -487,6 +487,21 @@ public abstract class ReturnTypes {
-1);
};
+ /**
+ * Returns the element type of a ARRAY or MULTISET.
+ *
+ * <p>For example, given <code>INTEGER ARRAY or MULTISET ARRAY</code>,
returns
+ * <code>INTEGER</code>.
+ */
+ public static final SqlReturnTypeInference TO_COLLECTION_ELEMENT =
+ ARG0.andThen(SqlTypeTransforms.TO_COLLECTION_ELEMENT_TYPE);
+
+ public static final SqlReturnTypeInference TO_COLLECTION_ELEMENT_NULLABLE =
+ TO_COLLECTION_ELEMENT.andThen(SqlTypeTransforms.TO_NULLABLE);
+
+ public static final SqlReturnTypeInference
TO_COLLECTION_ELEMENT_FORCE_NULLABLE =
+ TO_COLLECTION_ELEMENT.andThen(SqlTypeTransforms.FORCE_NULLABLE);
+
/**
* Returns a MULTISET type.
*
@@ -500,7 +515,7 @@ public abstract class ReturnTypes {
* Returns the element type of a MULTISET.
*/
public static final SqlReturnTypeInference MULTISET_ELEMENT_NULLABLE =
- MULTISET.andThen(SqlTypeTransforms.TO_MULTISET_ELEMENT_TYPE);
+ MULTISET.andThen(SqlTypeTransforms.TO_COLLECTION_ELEMENT_TYPE);
/**
* Same as {@link #MULTISET} but returns with nullability if any of the
diff --git
a/core/src/main/java/org/apache/calcite/sql/type/SqlTypeTransforms.java
b/core/src/main/java/org/apache/calcite/sql/type/SqlTypeTransforms.java
index 4adb1133c5..f4602cfe81 100644
--- a/core/src/main/java/org/apache/calcite/sql/type/SqlTypeTransforms.java
+++ b/core/src/main/java/org/apache/calcite/sql/type/SqlTypeTransforms.java
@@ -155,11 +155,12 @@ public abstract class SqlTypeTransforms {
/**
* Parameter type-inference transform strategy where a derived type must be
- * a multiset type and the returned type is the multiset's element type.
+ * a multiset or array type and the returned type is element type.
*
* @see MultisetSqlType#getComponentType
+ * @see ArraySqlType#getComponentType
*/
- public static final SqlTypeTransform TO_MULTISET_ELEMENT_TYPE =
+ public static final SqlTypeTransform TO_COLLECTION_ELEMENT_TYPE =
(opBinding, typeToTransform) -> requireNonNull(
typeToTransform.getComponentType(),
() -> "componentType for " + typeToTransform + " in opBinding " +
opBinding);
diff --git a/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
b/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
index ff13006a22..cfc51dfd38 100644
--- a/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
+++ b/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
@@ -630,6 +630,8 @@ public enum BuiltInMethod {
Collection.class),
ARRAY_COMPACT(SqlFunctions.class, "compact", List.class),
ARRAY_DISTINCT(SqlFunctions.class, "distinct", List.class),
+ ARRAY_MAX(SqlFunctions.class, "arrayMax", List.class),
+ ARRAY_MIN(SqlFunctions.class, "arrayMin", List.class),
ARRAY_REPEAT(SqlFunctions.class, "repeat", Object.class, Integer.class),
ARRAY_REVERSE(SqlFunctions.class, "reverse", List.class),
MAP_ENTRIES(SqlFunctions.class, "mapEntries", Map.class),
diff --git a/site/_docs/reference.md b/site/_docs/reference.md
index cc143f2ee2..a2a816cbfb 100644
--- a/site/_docs/reference.md
+++ b/site/_docs/reference.md
@@ -2656,6 +2656,8 @@ BigQuery's type system uses confusingly different names
for types and functions:
| b | ARRAY_CONCAT(array [, array ]*) | Concatenates one or
more arrays. If any input argument is `NULL` the function returns `NULL`
| s | ARRAY_DISTINCT(array) | Returns unique elements
of *array*. Keeps ordering of elements.
| b | ARRAY_LENGTH(array) | Synonym for
`CARDINALITY`
+| s | ARRAY_MAX(array) | Returns the maximum
value in the *array*
+| s | ARRAY_MIN(array) | Returns the minimum
value in the *array*
| s | ARRAY_REPEAT(element, count) | Returns the array
containing element count times.
| b | ARRAY_REVERSE(array) | Reverses elements of
*array*
| s | ARRAY_SIZE(array) | Synonym for
`CARDINALITY`
diff --git a/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java
b/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java
index aa3ae30eeb..ad7ae34667 100644
--- a/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java
+++ b/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java
@@ -5376,6 +5376,37 @@ public class SqlOperatorTest {
f.checkNull("array_distinct(null)");
}
+ /** Tests {@code ARRAY_MAX} function from Spark. */
+ @Test void testArrayMaxFunc() {
+ final SqlOperatorFixture f0 = fixture();
+ f0.setFor(SqlLibraryOperators.ARRAY_MAX);
+ f0.checkFails("^array_max(array[1, 2])^",
+ "No match found for function signature ARRAY_MAX\\(<INTEGER
ARRAY>\\)", false);
+
+ final SqlOperatorFixture f = f0.withLibrary(SqlLibrary.SPARK);
+ f.checkScalar("array_max(array[1, 2])", "2", "INTEGER");
+ f.checkScalar("array_max(array[1, 2, null])", "2", "INTEGER");
+ f.checkScalar("array_max(array[1])", "1", "INTEGER");
+ f.checkType("array_max(array())", "UNKNOWN");
+ f.checkNull("array_max(array())");
+ f.checkNull("array_max(cast(null as integer array))");
+ }
+
+ /** Tests {@code ARRAY_MIN} function from Spark. */
+ @Test void testArrayMinFunc() {
+ final SqlOperatorFixture f0 = fixture();
+ f0.setFor(SqlLibraryOperators.ARRAY_MIN);
+ f0.checkFails("^array_min(array[1, 2])^",
+ "No match found for function signature ARRAY_MIN\\(<INTEGER
ARRAY>\\)", false);
+
+ final SqlOperatorFixture f = f0.withLibrary(SqlLibrary.SPARK);
+ f.checkScalar("array_min(array[1, 2])", "1", "INTEGER");
+ f.checkScalar("array_min(array[1, 2, null])", "1", "INTEGER");
+ f.checkType("array_min(array())", "UNKNOWN");
+ f.checkNull("array_min(array())");
+ f.checkNull("array_min(cast(null as integer array))");
+ }
+
/** Tests {@code ARRAY_REPEAT} function from Spark. */
@Test void testArrayRepeatFunc() {
final SqlOperatorFixture f0 = fixture();