You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by ch...@apache.org on 2022/05/12 02:51:31 UTC
[calcite] branch main updated: [CALCITE-5125] Extend "||" operator to work with arrays
This is an automated email from the ASF dual-hosted git repository.
chunwei 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 b7dbee54df [CALCITE-5125] Extend "||" operator to work with arrays
b7dbee54df is described below
commit b7dbee54df60720ece301ba39cd928844e1a42ee
Author: dssysolyatin <dm...@gmail.com>
AuthorDate: Fri Apr 29 16:24:40 2022 +0300
[CALCITE-5125] Extend "||" operator to work with arrays
Close apache/calcite#2787
---
.../calcite/adapter/enumerable/RexImpTable.java | 26 ++++++++++++++++++++--
.../calcite/sql/fun/SqlStdOperatorTable.java | 18 ++++++++++++---
.../org/apache/calcite/sql/type/OperandTypes.java | 5 ++++-
.../org/apache/calcite/test/SqlOperatorTest.java | 9 ++++++++
4 files changed, 52 insertions(+), 6 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 3f58b9a678..9738523f2c 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
@@ -373,8 +373,7 @@ public class RexImpTable {
NullPolicy.STRICT);
defineMethod(OCTET_LENGTH, BuiltInMethod.OCTET_LENGTH.method,
NullPolicy.STRICT);
- defineMethod(CONCAT, BuiltInMethod.STRING_CONCAT.method,
- NullPolicy.STRICT);
+ map.put(CONCAT, new ConcatImplementor());
defineMethod(CONCAT_FUNCTION, BuiltInMethod.MULTI_STRING_CONCAT.method,
NullPolicy.STRICT);
defineMethod(CONCAT2, BuiltInMethod.STRING_CONCAT.method, NullPolicy.STRICT);
@@ -2699,6 +2698,29 @@ public class RexImpTable {
}
}
+ /** Implementor for a array or string concat. */
+ private static class ConcatImplementor extends AbstractRexCallImplementor {
+ private ArrayConcatImplementor arrayConcatImplementor =
+ new ArrayConcatImplementor();
+ private MethodImplementor stringConcatImplementor
+ = new MethodImplementor(BuiltInMethod.STRING_CONCAT.method, NullPolicy.STRICT, false);
+ ConcatImplementor() {
+ super(NullPolicy.STRICT, false);
+ }
+
+ @Override String getVariableName() {
+ return "concat";
+ }
+
+ @Override Expression implementSafe(RexToLixTranslator translator, RexCall call,
+ List<Expression> argValueList) {
+ if (call.type.getSqlTypeName() == SqlTypeName.ARRAY) {
+ return arrayConcatImplementor.implementSafe(translator, call, argValueList);
+ }
+ return stringConcatImplementor.implementSafe(translator, call, argValueList);
+ }
+ }
+
/** Implementor for a value-constructor. */
private static class ValueConstructorImplementor
extends AbstractRexCallImplementor {
diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java
index ab1b554e3a..882202f91c 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java
@@ -61,6 +61,8 @@ import org.apache.calcite.sql.type.InferTypes;
import org.apache.calcite.sql.type.OperandTypes;
import org.apache.calcite.sql.type.ReturnTypes;
import org.apache.calcite.sql.type.SqlOperandCountRanges;
+import org.apache.calcite.sql.type.SqlReturnTypeInference;
+import org.apache.calcite.sql.type.SqlTypeFamily;
import org.apache.calcite.sql.type.SqlTypeName;
import org.apache.calcite.sql.util.ReflectiveSqlOperatorTable;
import org.apache.calcite.sql.validate.SqlConformance;
@@ -248,7 +250,7 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
public static final SqlInternalOperator EXTEND = new SqlExtendOperator();
/**
- * String concatenation operator, '<code>||</code>'.
+ * String and array-to-array concatenation operator, '<code>||</code>'.
*
* @see SqlLibraryOperators#CONCAT_FUNCTION
*/
@@ -258,9 +260,19 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
SqlKind.OTHER,
60,
true,
- ReturnTypes.DYADIC_STRING_SUM_PRECISION_NULLABLE,
+ ReturnTypes.ARG0.andThen((opBinding, typeToTransform) -> {
+ SqlReturnTypeInference returnType =
+ typeToTransform.getSqlTypeName().getFamily() == SqlTypeFamily.ARRAY
+ ? ReturnTypes.LEAST_RESTRICTIVE
+ : ReturnTypes.DYADIC_STRING_SUM_PRECISION_NULLABLE;
+
+ return requireNonNull(returnType.inferReturnType(opBinding),
+ "inferred CONCAT element type");
+ }),
null,
- OperandTypes.STRING_SAME_SAME);
+ OperandTypes.STRING_SAME_SAME_OR_ARRAY_SAME_SAME
+ );
+
/**
* Arithmetic division operator, '<code>/</code>'.
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 534e298b29..67db9053e7 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
@@ -288,7 +288,6 @@ public abstract class OperandTypes {
public static final SqlSingleOperandTypeChecker ARRAY =
family(SqlTypeFamily.ARRAY);
-
/** Checks that returns whether a value is a multiset or an array.
* Cf Java, where list and set are collections but a map is not. */
public static final SqlSingleOperandTypeChecker COLLECTION =
@@ -520,6 +519,10 @@ public abstract class OperandTypes {
public static final SqlSingleOperandTypeChecker STRING_SAME_SAME_INTEGER =
OperandTypes.and(STRING_STRING_INTEGER, SAME_SAME_INTEGER);
+ public static final SqlSingleOperandTypeChecker STRING_SAME_SAME_OR_ARRAY_SAME_SAME =
+ or(STRING_SAME_SAME,
+ and(OperandTypes.SAME_SAME, family(SqlTypeFamily.ARRAY, SqlTypeFamily.ARRAY)));
+
public static final SqlSingleOperandTypeChecker ANY =
family(SqlTypeFamily.ANY);
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 a2337fd985..26919dfb9a 100644
--- a/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java
+++ b/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java
@@ -1776,6 +1776,15 @@ public class SqlOperatorTest {
f.checkNull(" cast(null as ANY) || cast(null as ANY) ");
f.checkString("cast('a' as varchar) || cast('b' as varchar) "
+ "|| cast('c' as varchar)", "abc", "VARCHAR NOT NULL");
+
+ f.checkScalar("array[1, 2] || array[2, 3]", "[1, 2, 2, 3]",
+ "INTEGER NOT NULL ARRAY NOT NULL");
+ f.checkScalar("array[1, 2] || array[2, null]", "[1, 2, 2, null]",
+ "INTEGER ARRAY NOT NULL");
+ f.checkScalar("array['hello', 'world'] || array['!'] || "
+ + "array[cast(null as char)]",
+ "[hello, world, !, null]", "CHAR(5) ARRAY NOT NULL");
+ f.checkNull("cast(null as integer array) || array[1]");
}
@Test void testConcatFunc() {