This is an automated email from the ASF dual-hosted git repository.
chunwei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/calcite.git
The following commit(s) were added to refs/heads/master by this push:
new f61541d [CALCITE-4822] Add functions ARRAY_CONCAT, ARRAY_REVERSE,
ARRAY_LENGTH for BigQuery dialect
f61541d is described below
commit f61541d633cfde53a4b0de0c23a010250c93274e
Author: snuyanzin <[email protected]>
AuthorDate: Tue May 11 21:21:29 2021 +0200
[CALCITE-4822] Add functions ARRAY_CONCAT, ARRAY_REVERSE, ARRAY_LENGTH for
BigQuery dialect
---
.../calcite/adapter/enumerable/RexImpTable.java | 39 ++++++++++++++++++++++
.../org/apache/calcite/runtime/SqlFunctions.java | 7 ++++
.../main/java/org/apache/calcite/sql/SqlKind.java | 6 ++++
.../calcite/sql/fun/SqlLibraryOperators.java | 30 +++++++++++++++++
.../org/apache/calcite/sql/type/OperandTypes.java | 12 +++++++
.../org/apache/calcite/util/BuiltInMethod.java | 5 ++-
.../calcite/sql/test/SqlOperatorBaseTest.java | 38 +++++++++++++++++++++
site/_docs/reference.md | 3 ++
8 files changed, 139 insertions(+), 1 deletion(-)
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 4aa6f4f..4921339 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
@@ -109,7 +109,10 @@ import static
org.apache.calcite.linq4j.tree.ExpressionType.Subtract;
import static org.apache.calcite.linq4j.tree.ExpressionType.UnaryPlus;
import static org.apache.calcite.sql.fun.SqlInternalOperators.THROW_UNLESS;
import static org.apache.calcite.sql.fun.SqlLibraryOperators.ARRAY_AGG;
+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_LENGTH;
+import static org.apache.calcite.sql.fun.SqlLibraryOperators.ARRAY_REVERSE;
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.CHR;
@@ -510,10 +513,14 @@ public class RexImpTable {
// Multisets & arrays
defineMethod(CARDINALITY, BuiltInMethod.COLLECTION_SIZE.method,
NullPolicy.STRICT);
+ defineMethod(ARRAY_LENGTH, BuiltInMethod.COLLECTION_SIZE.method,
+ NullPolicy.STRICT);
defineMethod(SLICE, BuiltInMethod.SLICE.method, NullPolicy.NONE);
defineMethod(ELEMENT, BuiltInMethod.ELEMENT.method, NullPolicy.STRICT);
defineMethod(STRUCT_ACCESS, BuiltInMethod.STRUCT_ACCESS.method,
NullPolicy.ANY);
defineMethod(MEMBER_OF, BuiltInMethod.MEMBER_OF.method, NullPolicy.NONE);
+ defineMethod(ARRAY_REVERSE, BuiltInMethod.ARRAY_REVERSE.method,
NullPolicy.STRICT);
+ map.put(ARRAY_CONCAT, new ArrayConcatImplementor());
final MethodImplementor isEmptyImplementor =
new MethodImplementor(BuiltInMethod.IS_EMPTY.method, NullPolicy.NONE,
false);
@@ -2657,6 +2664,38 @@ public class RexImpTable {
}
}
+ /** Implementor for a array concat. */
+ private static class ArrayConcatImplementor extends
AbstractRexCallImplementor {
+
+ ArrayConcatImplementor() {
+ super(NullPolicy.STRICT, false);
+ }
+
+ @Override String getVariableName() {
+ return "array_concat";
+ }
+
+ @Override Expression implementSafe(RexToLixTranslator translator, RexCall
call,
+ List<Expression> argValueList) {
+ final BlockBuilder blockBuilder = translator.getBlockBuilder();
+ final Expression list =
+ blockBuilder.append("list", Expressions.new_(ArrayList.class),
false);
+ final Expression nullValue = Expressions.constant(null);
+ for (Expression expression : argValueList) {
+ blockBuilder.add(
+ Expressions.ifThenElse(
+ Expressions.or(
+ Expressions.equal(nullValue, list),
+ Expressions.equal(nullValue, expression)),
+ Expressions.assign(list, nullValue),
+ Expressions.statement(
+ Expressions.call(list,
BuiltInMethod.COLLECTION_ADDALL.method, expression)))
+ );
+ }
+ return list;
+ }
+ }
+
/** Implementor for a value-constructor. */
private static class ValueConstructorImplementor
extends AbstractRexCallImplementor {
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 382e091..17eeb00 100644
--- a/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
+++ b/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
@@ -63,6 +63,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.Collection;
+import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
@@ -2788,6 +2789,12 @@ public class SqlFunctions {
return resultCollection;
}
+ /** Support the ARRAY_REVERSE function. */
+ public static List reverse(List list) {
+ Collections.reverse(list);
+ return list;
+ }
+
/**
* Function that, given a certain List containing single-item structs (i.e.
arrays / lists with
* a single item), builds an Enumerable that returns those single items
inside the structs.
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 ae68852..7dcfd07 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlKind.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlKind.java
@@ -635,6 +635,12 @@ public enum SqlKind {
/** {@code EXTRACT} function. */
EXTRACT,
+ /** {@code ARRAY_CONCAT} function (BigQuery semantics). */
+ ARRAY_CONCAT,
+
+ /** {@code ARRAY_REVERSE} function (BigQuery semantics). */
+ ARRAY_REVERSE,
+
/** {@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 7879564..0df5f8c 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
@@ -525,6 +525,36 @@ public abstract class SqlLibraryOperators {
OperandTypes.STRING_SAME_SAME,
SqlFunctionCategory.STRING);
+ /** The "ARRAY_LENGTH(array)" function. */
+ @LibraryOperator(libraries = {BIG_QUERY})
+ public static final SqlFunction ARRAY_LENGTH =
+ new SqlFunction("ARRAY_LENGTH",
+ SqlKind.OTHER_FUNCTION,
+ ReturnTypes.INTEGER_NULLABLE,
+ null,
+ OperandTypes.ARRAY,
+ SqlFunctionCategory.SYSTEM);
+
+ /** The "ARRAY_REVERSE(array)" function. */
+ @LibraryOperator(libraries = {BIG_QUERY})
+ public static final SqlFunction ARRAY_REVERSE =
+ new SqlFunction("ARRAY_REVERSE",
+ SqlKind.ARRAY_REVERSE,
+ ReturnTypes.ARG0_NULLABLE,
+ null,
+ OperandTypes.ARRAY,
+ SqlFunctionCategory.SYSTEM);
+
+ /** The "ARRAY_CONCAT(array [, array]*)" function. */
+ @LibraryOperator(libraries = {BIG_QUERY})
+ public static final SqlFunction ARRAY_CONCAT =
+ new SqlFunction("ARRAY_CONCAT",
+ SqlKind.ARRAY_CONCAT,
+ ReturnTypes.LEAST_RESTRICTIVE,
+ null,
+ OperandTypes.AT_LEAST_ONE_SAME_VARIADIC,
+ SqlFunctionCategory.SYSTEM);
+
@LibraryOperator(libraries = {MYSQL})
public static final SqlFunction REVERSE =
new SqlFunction("REVERSE",
diff --git a/core/src/main/java/org/apache/calcite/sql/type/OperandTypes.java
b/core/src/main/java/org/apache/calcite/sql/type/OperandTypes.java
index 1658cb8..534e298 100644
--- a/core/src/main/java/org/apache/calcite/sql/type/OperandTypes.java
+++ b/core/src/main/java/org/apache/calcite/sql/type/OperandTypes.java
@@ -437,6 +437,18 @@ public abstract class OperandTypes {
new SameOperandTypeChecker(-1);
/**
+ * Operand type-checking strategy where any positive number of operands must
all be
+ * in the same type family.
+ */
+ public static final SqlOperandTypeChecker AT_LEAST_ONE_SAME_VARIADIC =
+ new SameOperandTypeChecker(-1) {
+ @Override public SqlOperandCountRange
+ getOperandCountRange() {
+ return SqlOperandCountRanges.from(1);
+ }
+ };
+
+ /**
* Operand type-checking strategy where operand types must allow ordered
* comparisons.
*/
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 2b4fa7a..510baf1 100644
--- a/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
+++ b/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
@@ -569,6 +569,7 @@ public enum BuiltInMethod {
IS_EMPTY(Collection.class, "isEmpty"),
SUBMULTISET_OF(SqlFunctions.class, "submultisetOf", Collection.class,
Collection.class),
+ ARRAY_REVERSE(SqlFunctions.class, "reverse", List.class),
SELECTIVITY(Selectivity.class, "getSelectivity", RexNode.class),
UNIQUE_KEYS(UniqueKeys.class, "getUniqueKeys", boolean.class),
AVERAGE_ROW_SIZE(Size.class, "averageRowSize"),
@@ -633,7 +634,9 @@ public enum BuiltInMethod {
long.class, long.class),
SESSIONIZATION(EnumUtils.class, "sessionize", Enumerator.class, int.class,
int.class,
long.class),
- BIG_DECIMAL_NEGATE(BigDecimal.class, "negate");
+ BIG_DECIMAL_ADD(BigDecimal.class, "add", BigDecimal.class),
+ BIG_DECIMAL_NEGATE(BigDecimal.class, "negate"),
+ COMPARE_TO(Comparable.class, "compareTo", Object.class);
@SuppressWarnings("ImmutableEnumChecker")
public final Method method;
diff --git
a/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java
b/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java
index 556c2c7..f3097ec 100644
--- a/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java
+++ b/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java
@@ -5760,6 +5760,44 @@ public abstract class SqlOperatorBaseTest {
tester.checkScalar("rand_integer(2, 11)", 1, "INTEGER NOT NULL");
}
+ /** Tests {@code ARRAY_CONCAT} function from BigQuery. */
+ @Test void testArrayConcat() {
+ SqlTester tester = libraryTester(SqlLibrary.BIG_QUERY);
+ tester.setFor(SqlLibraryOperators.ARRAY_CONCAT);
+ tester.checkFails("^array_concat()^", INVALID_ARGUMENTS_NUMBER, false);
+ tester.checkScalar("array_concat(array[1, 2], array[2, 3])", "[1, 2, 2,
3]",
+ "INTEGER NOT NULL ARRAY NOT NULL");
+ tester.checkScalar("array_concat(array[1, 2], array[2, null])", "[1, 2, 2,
null]",
+ "INTEGER ARRAY NOT NULL");
+ tester.checkScalar(
+ "array_concat(array['hello', 'world'], array['!'], array[cast(null as
char)])",
+ "[hello, world, !, null]", "CHAR(5) ARRAY NOT NULL");
+ tester.checkNull("array_concat(cast(null as integer array), array[1])");
+ }
+
+ /** Tests {@code ARRAY_REVERSE} function from BigQuery. */
+ @Test void testArrayReverseFunc() {
+ SqlTester tester = libraryTester(SqlLibrary.BIG_QUERY);
+ tester.setFor(SqlLibraryOperators.ARRAY_REVERSE);
+ tester.checkScalar("array_reverse(array[1])", "[1]",
+ "INTEGER NOT NULL ARRAY NOT NULL");
+ tester.checkScalar("array_reverse(array[1, 2])", "[2, 1]",
+ "INTEGER NOT NULL ARRAY NOT NULL");
+ tester.checkScalar("array_reverse(array[null, 1])", "[1, null]",
+ "INTEGER ARRAY NOT NULL");
+ }
+
+ /** Tests {@code ARRAY_LENGTH} function from BigQuery. */
+ @Test void testArrayLengthFunc() {
+ SqlTester tester = libraryTester(SqlLibrary.BIG_QUERY);
+ tester.setFor(SqlLibraryOperators.ARRAY_LENGTH);
+ tester.checkScalar("array_length(array[1])", "1",
+ "INTEGER NOT NULL");
+ tester.checkScalar("array_length(array[1, 2, null])", "3",
+ "INTEGER NOT NULL");
+ tester.checkNull("array_length(null)");
+ }
+
/** Tests {@code UNIX_SECONDS} and other datetime functions from BigQuery. */
@Test void testUnixSecondsFunc() {
SqlTester tester = libraryTester(SqlLibrary.BIG_QUERY);
diff --git a/site/_docs/reference.md b/site/_docs/reference.md
index f186cca..2afd767 100644
--- a/site/_docs/reference.md
+++ b/site/_docs/reference.md
@@ -2513,6 +2513,9 @@ semantics.
| C | Operator syntax | Description
|:- |:-----------------------------------------------|:-----------
| p | expr :: type | Casts *expr* to *type*
+| b | ARRAY_CONCAT(array [, array ]*) | Concatenates one or
more arrays. If any input argument is `NULL` the function returns `NULL`
+| b | ARRAY_LENGTH(array) | Synonym for
`CARDINALITY`
+| b | ARRAY_REVERSE(array) | Reverses elements of
*array*
| o | CHR(integer) | Returns the character having the binary equivalent to
*integer* as a CHAR value
| o | COSH(numeric) | Returns the hyperbolic
cosine of *numeric*
| o | CONCAT(string, string) | Concatenates two strings