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

taiyangli pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-gluten.git


The following commit(s) were added to refs/heads/main by this push:
     new feed276ab6 [GLUTEN-9083][CH] Fix array_sort exception (#9040)
feed276ab6 is described below

commit feed276ab6ce71cb57d4e9a9af57aaf2122f7292
Author: 李扬 <[email protected]>
AuthorDate: Tue Mar 18 18:29:07 2025 +0800

    [GLUTEN-9083][CH] Fix array_sort exception (#9040)
    
    * fix array_sort issue
    
    * revert tests
---
 .../execution/GlutenClickHouseTPCHNullableSuite.scala |  5 +++++
 .../arrayHighOrderFunctions.cpp                       | 19 ++++++++++++++++++-
 2 files changed, 23 insertions(+), 1 deletion(-)

diff --git 
a/backends-clickhouse/src/test/scala/org/apache/gluten/execution/GlutenClickHouseTPCHNullableSuite.scala
 
b/backends-clickhouse/src/test/scala/org/apache/gluten/execution/GlutenClickHouseTPCHNullableSuite.scala
index e33d241510..89c094f268 100644
--- 
a/backends-clickhouse/src/test/scala/org/apache/gluten/execution/GlutenClickHouseTPCHNullableSuite.scala
+++ 
b/backends-clickhouse/src/test/scala/org/apache/gluten/execution/GlutenClickHouseTPCHNullableSuite.scala
@@ -252,4 +252,9 @@ class GlutenClickHouseTPCHNullableSuite extends 
GlutenClickHouseTPCHAbstractSuit
         }
       })
   }
+
+  test("Fix array_sort issue-9038") {
+    val sql = "select array_sort(split(l_comment, ' ')) from lineitem limit 10"
+    runSql(sql) { _ => }
+  }
 }
diff --git 
a/cpp-ch/local-engine/Parser/scalar_function_parser/arrayHighOrderFunctions.cpp 
b/cpp-ch/local-engine/Parser/scalar_function_parser/arrayHighOrderFunctions.cpp
index 3a06c77c7a..6b735ed175 100644
--- 
a/cpp-ch/local-engine/Parser/scalar_function_parser/arrayHighOrderFunctions.cpp
+++ 
b/cpp-ch/local-engine/Parser/scalar_function_parser/arrayHighOrderFunctions.cpp
@@ -100,7 +100,7 @@ public:
             /// The difference of both types will result in runtime exceptions 
in function capture.
             const auto & src_array_type = parsed_args[0]->result_type;
             DataTypePtr dst_array_type = 
std::make_shared<DataTypeArray>(lambda_args.front().type);
-            if (isNullableOrLowCardinalityNullable(src_array_type))
+            if (src_array_type->isNullable())
                 dst_array_type = 
std::make_shared<DataTypeNullable>(dst_array_type);
             const auto * dst_array_arg = 
ActionsDAGUtil::convertNodeTypeIfNeeded(actions_dag, parsed_args[0], 
dst_array_type);
             return toFunctionNode(actions_dag, ch_func_name, {parsed_args[1], 
dst_array_arg});
@@ -170,13 +170,16 @@ class FunctionParserArraySort : public FunctionParser
 {
 public:
     static constexpr auto name = "array_sort";
+
     explicit FunctionParserArraySort(ParserContextPtr parser_context_) : 
FunctionParser(parser_context_) {}
     ~FunctionParserArraySort() override = default;
+
     String getName() const override { return name; }
     String getCHFunctionName(const substrait::Expression_ScalarFunction & 
scalar_function) const override
     {
         return "arraySortSpark";
     }
+
     const DB::ActionsDAG::Node *
     parse(const substrait::Expression_ScalarFunction & substrait_func, 
DB::ActionsDAG & actions_dag) const override
     {
@@ -191,6 +194,20 @@ public:
             return toFunctionNode(actions_dag, ch_func_name, {parsed_args[0]});
         }
 
+        auto lambda_args = collectLambdaArguments(parser_context, 
substrait_func.arguments()[1].value().scalar_function());
+        if (lambda_args.size() != 2 || 
!lambda_args.front().type->equals(*(lambda_args.back().type)))
+            throw DB::Exception(
+                DB::ErrorCodes::BAD_ARGUMENTS, "array_sort function must have 
a lambda function with two arguments of the same type");
+
+        /// In case lambda argument types are T, and the array has type 
Array(Nullable(T)) or Nullable(Array(Nullable(T))).
+        /// We need to convert the array type to Array(T) or 
Nullable(Array(T)) to match the lambda argument types, otherwise it will cause 
runtime exceptions
+        /// in function capture.
+        const auto & src_array_type = parsed_args[0]->result_type;
+        DataTypePtr dst_array_type = 
std::make_shared<DataTypeArray>(lambda_args.front().type);
+        if (src_array_type->isNullable())
+            dst_array_type = 
std::make_shared<DataTypeNullable>(dst_array_type);
+        parsed_args[0] = ActionsDAGUtil::convertNodeTypeIfNeeded(actions_dag, 
parsed_args[0], dst_array_type);
+
         return toFunctionNode(actions_dag, ch_func_name, {parsed_args[1], 
parsed_args[0]});
     }
 private:


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to