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 48f51ea5d9 [CALCITE-5700] Add ARRAY_SIZE, ARRAY_REPEAT function (enabled in Spark library). 48f51ea5d9 is described below commit 48f51ea5d9443fb11e070eea094bf551c8ff22fc Author: yongen.ly <yongen...@alibaba-inc.com> AuthorDate: Fri May 12 15:06:00 2023 +0800 [CALCITE-5700] Add ARRAY_SIZE, ARRAY_REPEAT function (enabled in Spark library). --- .../calcite/adapter/enumerable/RexImpTable.java | 4 +++ .../org/apache/calcite/runtime/SqlFunctions.java | 12 ++++++++ .../main/java/org/apache/calcite/sql/SqlKind.java | 6 ++++ .../calcite/sql/fun/SqlLibraryOperators.java | 16 ++++++++++ .../org/apache/calcite/util/BuiltInMethod.java | 1 + site/_docs/reference.md | 2 ++ .../org/apache/calcite/test/SqlOperatorTest.java | 36 ++++++++++++++++++++++ 7 files changed, 77 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 bf835c0d18..16a9df8632 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 @@ -118,7 +118,9 @@ 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_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.BOOL_AND; import static org.apache.calcite.sql.fun.SqlLibraryOperators.BOOL_OR; import static org.apache.calcite.sql.fun.SqlLibraryOperators.CHAR; @@ -671,7 +673,9 @@ public class RexImpTable { defineMethod(STRUCT_ACCESS, BuiltInMethod.STRUCT_ACCESS.method, NullPolicy.ANY); defineMethod(MEMBER_OF, BuiltInMethod.MEMBER_OF.method, NullPolicy.NONE); defineMethod(ARRAY_DISTINCT, BuiltInMethod.ARRAY_DISTINCT.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); map.put(ARRAY_CONCAT, new ArrayConcatImplementor()); final MethodImplementor isEmptyImplementor = new MethodImplementor(BuiltInMethod.IS_EMPTY.method, NullPolicy.NONE, 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 75ced53c9a..52c2da6878 100644 --- a/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java +++ b/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java @@ -3797,6 +3797,18 @@ public class SqlFunctions { return new ArrayList<>(result); } + /** Support the ARRAY_REPEAT function. */ + public static @Nullable List<Object> repeat(Object element, Object count) { + if (count == null) { + return null; + } + int numberOfElement = (int) count; + if (numberOfElement < 0) { + numberOfElement = 0; + } + return Collections.nCopies(numberOfElement, element); + } + /** Support the SLICE function. */ public static List slice(List list) { List result = new ArrayList(list.size()); 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 44cd4cd02d..9104af350c 100644 --- a/core/src/main/java/org/apache/calcite/sql/SqlKind.java +++ b/core/src/main/java/org/apache/calcite/sql/SqlKind.java @@ -683,9 +683,15 @@ public enum SqlKind { /** {@code ARRAY_DISTINCT} function (Spark semantics). */ ARRAY_DISTINCT, + /** {@code ARRAY_REPEAT} function (Spark semantics). */ + ARRAY_REPEAT, + /** {@code ARRAY_REVERSE} function (BigQuery semantics). */ ARRAY_REVERSE, + /** {@code ARRAY_SIZE} function (Spark semantics). */ + ARRAY_SIZE, + /** {@code REVERSE} function (SQL Server, MySQL). */ REVERSE, 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 7eedae2918..4ae48490e5 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 @@ -858,6 +858,15 @@ public abstract class SqlLibraryOperators { ReturnTypes.INTEGER_NULLABLE, OperandTypes.ARRAY); + /** The "ARRAY_REPEAT(element, count)" function. */ + @LibraryOperator(libraries = {SPARK}) + public static final SqlFunction ARRAY_REPEAT = + SqlBasicFunction.create(SqlKind.ARRAY_REPEAT, + ReturnTypes.TO_ARRAY, + OperandTypes.sequence( + "ARRAY_REPEAT(ANY, INTEGER)", + OperandTypes.ANY, OperandTypes.typeName(SqlTypeName.INTEGER))); + /** The "ARRAY_REVERSE(array)" function. */ @LibraryOperator(libraries = {BIG_QUERY}) public static final SqlFunction ARRAY_REVERSE = @@ -865,6 +874,13 @@ public abstract class SqlLibraryOperators { ReturnTypes.ARG0_NULLABLE, OperandTypes.ARRAY); + /** The "ARRAY_SIZE(array)" function. */ + @LibraryOperator(libraries = {SPARK}) + public static final SqlFunction ARRAY_SIZE = + SqlBasicFunction.create(SqlKind.ARRAY_SIZE, + ReturnTypes.INTEGER_NULLABLE, + OperandTypes.ARRAY); + /** The "ARRAY_CONCAT(array [, array]*)" function. */ @LibraryOperator(libraries = {BIG_QUERY}) public static final SqlFunction ARRAY_CONCAT = 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 90eb4df0fc..13bc6ec051 100644 --- a/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java +++ b/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java @@ -629,6 +629,7 @@ public enum BuiltInMethod { SUBMULTISET_OF(SqlFunctions.class, "submultisetOf", Collection.class, Collection.class), ARRAY_DISTINCT(SqlFunctions.class, "distinct", List.class), + ARRAY_REPEAT(SqlFunctions.class, "repeat", Object.class, Integer.class), ARRAY_REVERSE(SqlFunctions.class, "reverse", List.class), SELECTIVITY(Selectivity.class, "getSelectivity", RexNode.class), UNIQUE_KEYS(UniqueKeys.class, "getUniqueKeys", boolean.class), diff --git a/site/_docs/reference.md b/site/_docs/reference.md index 30631bee36..47262a2d71 100644 --- a/site/_docs/reference.md +++ b/site/_docs/reference.md @@ -2654,7 +2654,9 @@ 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_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` | m s | CHAR(integer) | Returns the character whose ASCII code is *integer* % 256, or null if *integer* < 0 | b o p | CHR(integer) | Returns the character whose UTF-8 code is *integer* | o | CONCAT(string, string) | Concatenates two strings 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 338ac1bebe..fe4a8cac0c 100644 --- a/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java +++ b/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java @@ -5336,6 +5336,27 @@ public class SqlOperatorTest { f.checkNull("array_distinct(null)"); } + /** Tests {@code ARRAY_REPEAT} function from Spark. */ + @Test void testArrayRepeatFunc() { + final SqlOperatorFixture f0 = fixture(); + f0.setFor(SqlLibraryOperators.ARRAY_REPEAT); + f0.checkFails("^array_repeat(1, 2)^", + "No match found for function signature ARRAY_REPEAT\\(<NUMERIC>, <NUMERIC>\\)", false); + + final SqlOperatorFixture f = f0.withLibrary(SqlLibrary.SPARK); + f.checkScalar("array_repeat(1, 2)", "[1, 1]", + "INTEGER NOT NULL ARRAY NOT NULL"); + f.checkScalar("array_repeat(1, -2)", "[]", + "INTEGER NOT NULL ARRAY NOT NULL"); + f.checkScalar("array_repeat(array[1, 2], 2)", "[[1, 2], [1, 2]]", + "INTEGER NOT NULL ARRAY NOT NULL ARRAY NOT NULL"); + f.checkScalar("array_repeat(map[1, 'a', 2, 'b'], 2)", "[{1=a, 2=b}, {1=a, 2=b}]", + "(INTEGER NOT NULL, CHAR(1) NOT NULL) MAP NOT NULL ARRAY NOT NULL"); + f.checkScalar("array_repeat(cast(null as integer), 2)", "[null, null]", + "INTEGER ARRAY NOT NULL"); + f.checkNull("array_repeat(1, null)"); + } + /** Tests {@code ARRAY_REVERSE} function from BigQuery. */ @Test void testArrayReverseFunc() { SqlOperatorFixture f = fixture() @@ -5349,6 +5370,21 @@ public class SqlOperatorTest { "INTEGER ARRAY NOT NULL"); } + /** Tests {@code ARRAY_SIZE} function from Spark. */ + @Test void testArraySizeFunc() { + final SqlOperatorFixture f0 = fixture(); + f0.setFor(SqlLibraryOperators.ARRAY_SIZE); + f0.checkFails("^array_size(array[1])^", + "No match found for function signature ARRAY_SIZE\\(<INTEGER ARRAY>\\)", false); + + final SqlOperatorFixture f = f0.withLibrary(SqlLibrary.SPARK); + f.checkScalar("array_size(array[1])", "1", + "INTEGER NOT NULL"); + f.checkScalar("array_size(array[1, 2, null])", "3", + "INTEGER NOT NULL"); + f.checkNull("array_size(null)"); + } + /** Tests {@code ARRAY_LENGTH} function from BigQuery. */ @Test void testArrayLengthFunc() { SqlOperatorFixture f = fixture()