You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kylin.apache.org by xx...@apache.org on 2023/05/06 06:59:08 UTC

[kylin] 07/38: KYLIN-5524 Supports CONCAT for variable arguments

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

xxyu pushed a commit to branch kylin5
in repository https://gitbox.apache.org/repos/asf/kylin.git

commit f929bd876ed54afbd1490d2717894288fd197ec6
Author: sibingzhang <74...@users.noreply.github.com>
AuthorDate: Tue Feb 14 13:54:41 2023 +0800

    KYLIN-5524 Supports CONCAT for variable arguments
---
 .../kylin/query/udf/stringUdf/ConcatUDF.java       | 45 +++++++++++++++++++---
 .../org/apache/kylin/query/udf/StringUDFTest.java  | 21 +++++++---
 .../kylin/query/runtime/ExpressionConverter.scala  |  2 +-
 3 files changed, 57 insertions(+), 11 deletions(-)

diff --git a/src/query/src/main/java/org/apache/kylin/query/udf/stringUdf/ConcatUDF.java b/src/query/src/main/java/org/apache/kylin/query/udf/stringUdf/ConcatUDF.java
index 01f16d47e6..841cc16bfe 100644
--- a/src/query/src/main/java/org/apache/kylin/query/udf/stringUdf/ConcatUDF.java
+++ b/src/query/src/main/java/org/apache/kylin/query/udf/stringUdf/ConcatUDF.java
@@ -18,14 +18,49 @@
 
 package org.apache.kylin.query.udf.stringUdf;
 
-import org.apache.calcite.linq4j.function.Parameter;
+import org.apache.calcite.adapter.enumerable.CallImplementor;
+import org.apache.calcite.adapter.enumerable.UdfMethodNameImplementor;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.sql.SqlFunction;
+import org.apache.calcite.sql.SqlFunctionCategory;
+import org.apache.calcite.sql.SqlIdentifier;
+import org.apache.calcite.sql.fun.udf.UdfDef;
+import org.apache.calcite.sql.parser.SqlParserPos;
+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.SqlTypeName;
+import org.apache.calcite.sql.type.SqlTypeTransforms;
 
-public class ConcatUDF {
+import java.util.Arrays;
+import java.util.stream.Collectors;
 
-    public String CONCAT(@Parameter(name = "col1") Object col1, @Parameter(name = "col2") Object col2) {
-        if (col1 == null || col2 == null) {
+public class ConcatUDF implements UdfDef {
+
+    private static final String FUNC_NAME = "CONCAT";
+
+    private ConcatUDF() {
+        throw new IllegalStateException("Utility class");
+    }
+
+    public static final SqlFunction OPERATOR = new SqlFunction(new SqlIdentifier(FUNC_NAME, SqlParserPos.ZERO),
+            ReturnTypes.cascade(opBinding -> {
+                int precision = opBinding.collectOperandTypes().stream().mapToInt(RelDataType::getPrecision).sum();
+                return opBinding.getTypeFactory().createSqlType(SqlTypeName.VARCHAR, precision);
+            }, SqlTypeTransforms.TO_NULLABLE),
+            (callBinding, returnType, operandTypes) -> Arrays.fill(operandTypes,
+                    callBinding.getTypeFactory().createJavaType(Object.class)),
+            OperandTypes.repeat(SqlOperandCountRanges.from(2), OperandTypes.ANY), null,
+            SqlFunctionCategory.USER_DEFINED_FUNCTION);
+
+    public static final CallImplementor IMPLEMENTOR = new UdfMethodNameImplementor(FUNC_NAME.toLowerCase(),
+            ConcatUDF.class);
+
+    public static String concat(Object... args) {
+        if (args == null) {
             return null;
         }
-        return "" + col1 + col2;
+
+        return Arrays.stream(args).map(String::valueOf).collect(Collectors.joining());
     }
 }
diff --git a/src/query/src/test/java/org/apache/kylin/query/udf/StringUDFTest.java b/src/query/src/test/java/org/apache/kylin/query/udf/StringUDFTest.java
index 543795a2aa..799660a37f 100644
--- a/src/query/src/test/java/org/apache/kylin/query/udf/StringUDFTest.java
+++ b/src/query/src/test/java/org/apache/kylin/query/udf/StringUDFTest.java
@@ -33,16 +33,27 @@ import org.junit.Test;
 public class StringUDFTest {
 
     @Test
-    public void testConcatUDF() throws Exception {
-        ConcatUDF cu = new ConcatUDF();
-        String str1 = cu.CONCAT("Apache ", "Kylin");
+    public void testConcatUDF() {
+        String str1 = ConcatUDF.concat("Apache ", "Kylin");
         assertEquals("Apache Kylin", str1);
 
-        String str2 = cu.CONCAT("", "Kylin");
+        String str2 = ConcatUDF.concat("", "Kylin");
         assertEquals("Kylin", str2);
 
-        String str3 = cu.CONCAT("Apache", "");
+        String str3 = ConcatUDF.concat("Apache", "");
         assertEquals("Apache", str3);
+
+        String str4 = ConcatUDF.concat("Apache", 1);
+        assertEquals("Apache1", str4);
+
+        String str5 = ConcatUDF.concat(1, 1);
+        assertEquals("11", str5);
+
+        String str6 = ConcatUDF.concat("Apache ", "Kylin", " Kyligence");
+        assertEquals("Apache Kylin Kyligence", str6);
+
+        String str7 = ConcatUDF.concat(null);
+        assertNull(str7);
     }
 
     @Test
diff --git a/src/spark-project/sparder/src/main/scala/org/apache/kylin/query/runtime/ExpressionConverter.scala b/src/spark-project/sparder/src/main/scala/org/apache/kylin/query/runtime/ExpressionConverter.scala
index a839116059..856c19f50f 100644
--- a/src/spark-project/sparder/src/main/scala/org/apache/kylin/query/runtime/ExpressionConverter.scala
+++ b/src/spark-project/sparder/src/main/scala/org/apache/kylin/query/runtime/ExpressionConverter.scala
@@ -284,7 +284,7 @@ object ExpressionConverter {
               else children.apply(2).asInstanceOf[Int]
             new Column(StringLocate(k_lit(children.head).expr, k_lit(children.apply(1)).expr, lit(pos).expr)) //position(substr,str,start)
           case "concat" =>
-            concat(k_lit(children.head), k_lit(children.apply(1)))
+            concat(children.map(k_lit): _*)
           case "concat_ws" =>
             concat_ws(children.head.toString, k_lit(children.apply(1)))
           case "split_part" =>