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

xiong 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 71c161df81 [CALCITE-6831] Add ARRAY_SLICE function(enabled in Hive 
Library)
71c161df81 is described below

commit 71c161df817d0093ccd97e8191c30bb68e38ff66
Author: xuyu <[email protected]>
AuthorDate: Thu Feb 13 20:13:38 2025 +0800

    [CALCITE-6831] Add ARRAY_SLICE function(enabled in Hive Library)
---
 .../calcite/adapter/enumerable/RexImpTable.java    |  2 +
 .../org/apache/calcite/runtime/SqlFunctions.java   |  9 +++++
 .../main/java/org/apache/calcite/sql/SqlKind.java  |  4 ++
 .../calcite/sql/fun/SqlLibraryOperators.java       |  9 +++++
 .../org/apache/calcite/util/BuiltInMethod.java     |  1 +
 site/_docs/reference.md                            |  1 +
 .../org/apache/calcite/test/SqlOperatorTest.java   | 43 ++++++++++++++++++++++
 7 files changed, 69 insertions(+)

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 da79c96c0f..d5b752dace 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
@@ -152,6 +152,7 @@
 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;
+import static org.apache.calcite.sql.fun.SqlLibraryOperators.ARRAY_SLICE;
 import static org.apache.calcite.sql.fun.SqlLibraryOperators.ARRAY_TO_STRING;
 import static org.apache.calcite.sql.fun.SqlLibraryOperators.ARRAY_UNION;
 import static org.apache.calcite.sql.fun.SqlLibraryOperators.ASIND;
@@ -1065,6 +1066,7 @@ void populate2() {
       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);
+      defineMethod(ARRAY_SLICE, BuiltInMethod.ARRAY_SLICE.method, 
NullPolicy.STRICT);
       defineMethod(ARRAY_TO_STRING, BuiltInMethod.ARRAY_TO_STRING.method,
           NullPolicy.STRICT);
       defineMethod(ARRAY_UNION, BuiltInMethod.ARRAY_UNION.method, 
NullPolicy.ANY);
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 9fa031c313..5cef5efeb2 100644
--- a/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
+++ b/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
@@ -6524,6 +6524,15 @@ public static List reverse(List list) {
     return list;
   }
 
+  /** SQL {@code ARRAY_SLICE(array, start, length)} function. */
+  public static List arraySlice(List list, int start, int length) {
+    // return empty list if start/length are out of range of the array
+    if (start + length > list.size()) {
+      return Collections.emptyList();
+    }
+    return list.subList(start, start + length);
+  }
+
   /** SQL {@code ARRAY_TO_STRING(array, delimiter)} function. */
   public static String arrayToString(List list, String delimiter) {
     return arrayToString(list, delimiter, 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 84744b4c62..a870757ef7 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlKind.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlKind.java
@@ -830,6 +830,9 @@ public enum SqlKind {
   /** {@code ARRAY_SIZE} function (Spark semantics). */
   ARRAY_SIZE,
 
+  /** {@code ARRAY_SLICE} function (Hive semantics). */
+  ARRAY_SLICE,
+
   /** {@code ARRAY_TO_STRING} function (BigQuery semantics). */
   ARRAY_TO_STRING,
 
@@ -1824,6 +1827,7 @@ public SqlKind getFunctionKind() {
     case ARRAY_REPEAT:
     case ARRAY_REVERSE:
     case ARRAY_SIZE:
+    case ARRAY_SLICE:
     case ARRAY_TO_STRING:
     case ARRAY_UNION:
     case ARRAYS_OVERLAP:
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 c617bac014..fce4d0bdc4 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
@@ -1653,6 +1653,15 @@ private static RelDataType 
arrayInsertReturnType(SqlOperatorBinding opBinding) {
           ReturnTypes.INTEGER_NULLABLE,
           OperandTypes.ARRAY);
 
+  /** The "ARRAY_SLICE(array, start, length)" function. */
+  @LibraryOperator(libraries = {HIVE})
+  public static final SqlFunction ARRAY_SLICE =
+      SqlBasicFunction.create(SqlKind.ARRAY_SLICE,
+          ReturnTypes.ARG0_NULLABLE,
+          OperandTypes.sequence(
+              "ARRAY_SLICE(ARRAY, INTEGER, INTEGER)",
+              OperandTypes.ARRAY, OperandTypes.INTEGER, OperandTypes.INTEGER));
+
   /** The "ARRAY_UNION(array1, array2)" function. */
   @LibraryOperator(libraries = {SPARK})
   public static final SqlFunction ARRAY_UNION =
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 fbbbbc980d..c1f5d7e440 100644
--- a/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
+++ b/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
@@ -866,6 +866,7 @@ public enum BuiltInMethod {
   ARRAY_INTERSECT(SqlFunctions.class, "arrayIntersect", List.class, 
List.class),
   ARRAY_UNION(SqlFunctions.class, "arrayUnion", List.class, List.class),
   ARRAY_REVERSE(SqlFunctions.class, "reverse", List.class),
+  ARRAY_SLICE(SqlFunctions.class, "arraySlice", List.class, int.class, 
int.class),
   ARRAYS_OVERLAP(SqlFunctions.class, "arraysOverlap", List.class, List.class),
   ARRAYS_ZIP(SqlFunctions.class, "arraysZip", List.class, List.class),
   EXISTS(SqlFunctions.class, "exists", List.class, Function1.class),
diff --git a/site/_docs/reference.md b/site/_docs/reference.md
index 480a19e867..811cddc025 100644
--- a/site/_docs/reference.md
+++ b/site/_docs/reference.md
@@ -2800,6 +2800,7 @@ ### Dialect-specific Operators
 | 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`
+| h | ARRAY_SLICE(array, start, length)              | Returns the subset or 
range of elements.
 | b | ARRAY_TO_STRING(array, delimiter [, nullText ])| Returns a concatenation 
of the elements in *array* as a STRING and take *delimiter* as the delimiter. 
If the *nullText* parameter is used, the function replaces any `NULL` values in 
the array with the value of *nullText*. If the *nullText* parameter is not 
used, the function omits the `NULL` value and its preceding delimiter. Returns 
`NULL` if any argument is `NULL`
 | s | ARRAY_UNION(array1, array2)                    | Returns an array of the 
elements in the union of *array1* and *array2*, without duplicates
 | s | ARRAYS_OVERLAP(array1, array2)                 | Returns true if *array1 
contains at least a non-null element present also in *array2*. If the arrays 
have no common element and they are both non-empty and either of them contains 
a null element null is returned, false otherwise
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 a76d9f3065..9bd07895d5 100644
--- a/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java
+++ b/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java
@@ -8204,6 +8204,49 @@ void checkRegexpExtract(SqlOperatorFixture f0, 
FunctionAlias functionAlias) {
         "DECIMAL(19, 0)");
   }
 
+  /** Test case for
+   * <a 
href="https://issues.apache.org/jira/browse/CALCITE-6831";>[CALCITE-6831]
+   * Add ARRAR_SLICE function (enabled in Hive library)</a>. */
+  @Test void testArraySlice() {
+    SqlOperatorFixture f0 = fixture().setFor(SqlLibraryOperators.ARRAY_SLICE);
+    final List<SqlLibrary> libraries =
+        ImmutableList.of(SqlLibrary.HIVE);
+    final Consumer<SqlOperatorFixture> consumer = f -> {
+      f.checkString("array_slice(array[1,2,3], 1, 2)",
+          "[2, 3]",
+          "INTEGER NOT NULL ARRAY NOT NULL");
+      f.checkString("array_slice(array[1,null,3], 1, 2)",
+          "[null, 3]",
+          "INTEGER ARRAY NOT NULL");
+      f.checkString("array_slice(array[1,2,3], 1, 10)",
+          "[]",
+          "INTEGER NOT NULL ARRAY NOT NULL");
+      f.checkString("array_slice(array['a','b','c','d'], 1, 3)",
+          "[b, c, d]",
+          "CHAR(1) NOT NULL ARRAY NOT NULL");
+      f.checkString("array_slice(array[null,null,null], 1, 2)",
+          "[null, null]",
+          "NULL ARRAY NOT NULL");
+      f.checkString("array_slice(array[1,2.2,3], 1, 2)",
+          "[2.2, 3.0]",
+          "DECIMAL(11, 1) NOT NULL ARRAY NOT NULL");
+      f.checkString("array_slice(array[1,cast(2 as double),3], 1, 2)",
+          "[2.0, 3.0]",
+          "DOUBLE NOT NULL ARRAY NOT NULL");
+      f.checkString("array_slice(array[1,2.2,3,null], 1, 3)",
+          "[2.2, 3.0, null]",
+                "DECIMAL(11, 1) ARRAY NOT NULL");
+      f.checkFails("array_slice(^array[1,2.2,'c']^, 1, 2)",
+                "Parameters must be of the same type", false);
+      f.checkFails("array_slice(array[null,null,null], -1, 2)",
+                "fromIndex = -1", true);
+      f.checkNull("array_slice(array[1,2,3], null, 2)");
+      f.checkNull("array_slice(array[1,2,3], null, null)");
+      f.checkNull("array_slice(array[1,2,3], 1, null)");
+    };
+    f0.forEachLibrary(libraries, consumer);
+  }
+
   /** Tests {@code ARRAY_POSITION} function from Spark. */
   @Test void testArrayPositionFunc() {
     final SqlOperatorFixture f0 = fixture();

Reply via email to