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

changchen 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 57085144ee [GLUTEN-7979][CH] Fix exception cause by one child of 
UnionExec outputs Array(Nothing) while the other outputs Array(String) (#7980)
57085144ee is described below

commit 57085144ee2ca6228dffdf15a1407e02c23ab41a
Author: 李扬 <[email protected]>
AuthorDate: Wed Nov 20 14:13:23 2024 +0800

    [GLUTEN-7979][CH] Fix exception cause by one child of UnionExec outputs 
Array(Nothing) while the other outputs Array(String) (#7980)
    
    * fix bugs
    
    * add uts
    
    * fix failed uts
    
    * fix style
    
    * fix failed uts
---
 .../GlutenClickHouseTPCHSaltNullParquetSuite.scala | 50 ++++++++++++++++++++++
 cpp-ch/local-engine/Common/CHUtil.cpp              | 16 +------
 cpp-ch/local-engine/Common/GlutenStringUtils.h     |  3 --
 .../Operator/PartitionColumnFillingTransform.cpp   |  7 +--
 cpp-ch/local-engine/Parser/FunctionExecutor.cpp    |  4 --
 .../local-engine/Parser/SerializedPlanParser.cpp   | 50 +++++++++++-----------
 cpp-ch/local-engine/Storages/IO/NativeReader.cpp   |  5 +++
 cpp-ch/local-engine/Storages/IO/NativeWriter.cpp   |  1 +
 .../Storages/SubstraitSource/FormatFile.cpp        | 13 ++++--
 .../Storages/SubstraitSource/FormatFile.h          |  8 +++-
 .../SubstraitSource/SubstraitFileSource.cpp        | 35 +++++++--------
 .../utils/clickhouse/ClickHouseTestSettings.scala  |  3 ++
 .../utils/clickhouse/ClickHouseTestSettings.scala  |  3 ++
 .../utils/clickhouse/ClickHouseTestSettings.scala  |  3 ++
 .../utils/clickhouse/ClickHouseTestSettings.scala  |  3 ++
 15 files changed, 129 insertions(+), 75 deletions(-)

diff --git 
a/backends-clickhouse/src/test/scala/org/apache/gluten/execution/tpch/GlutenClickHouseTPCHSaltNullParquetSuite.scala
 
b/backends-clickhouse/src/test/scala/org/apache/gluten/execution/tpch/GlutenClickHouseTPCHSaltNullParquetSuite.scala
index 865d3fa40c..5d7bcf324a 100644
--- 
a/backends-clickhouse/src/test/scala/org/apache/gluten/execution/tpch/GlutenClickHouseTPCHSaltNullParquetSuite.scala
+++ 
b/backends-clickhouse/src/test/scala/org/apache/gluten/execution/tpch/GlutenClickHouseTPCHSaltNullParquetSuite.scala
@@ -2458,6 +2458,56 @@ class GlutenClickHouseTPCHSaltNullParquetSuite extends 
GlutenClickHouseTPCHAbstr
     runQueryAndCompare(sql, noFallBack = true)({ _ => })
   }
 
+  test("GLUTEN-7979: fix different output schema array<void> and array<string> 
before union") {
+    val sql =
+      """
+        |select
+        |    a.multi_peer_user_id,
+        |    max(a.user_id) as max_user_id,
+        |    max(a.peer_user_id) as max_peer_user_id,
+        |    max(a.is_match_line) as max_is_match_line
+        |from
+        |(
+        |    select
+        |        t1.user_id,
+        |        t1.peer_user_id,
+        |        t1.is_match_line,
+        |        t1.pk_type,
+        |        t1.pk_start_time,
+        |        t1.pk_end_time,
+        |        t1.multi_peer_user_id
+        |    from
+        |    (
+        |        select
+        |            id as user_id,
+        |            id as peer_user_id,
+        |            id % 2 as is_match_line,
+        |            id % 3 as pk_type,
+        |            id as pk_start_time,
+        |            id as pk_end_time,
+        |            array() as multi_peer_user_id
+        |        from range(10)
+        |
+        |        union all
+        |
+        |        select
+        |            id as user_id,
+        |            id as peer_user_id,
+        |            id % 2 as is_match_line,
+        |            id % 3 as pk_type,
+        |            id as pk_start_time,
+        |            id as pk_end_time,
+        |            array('a', 'b', 'c') as multi_peer_user_id
+        |        from range(10)
+        |    ) t1
+        |    where t1.user_id > 0 and t1.peer_user_id > 0
+        |) a
+        |group by
+        |    a.multi_peer_user_id
+        |""".stripMargin
+    runQueryAndCompare(sql, noFallBack = true)({ _ => })
+  }
+
   test("GLUTEN-4190: crush on flattening a const null column") {
     val sql =
       """
diff --git a/cpp-ch/local-engine/Common/CHUtil.cpp 
b/cpp-ch/local-engine/Common/CHUtil.cpp
index 2413fae9e3..6e907266ff 100644
--- a/cpp-ch/local-engine/Common/CHUtil.cpp
+++ b/cpp-ch/local-engine/Common/CHUtil.cpp
@@ -492,21 +492,7 @@ std::optional<DB::ColumnWithTypeAndName> 
NestedColumnExtractHelper::extractColum
 
 const DB::ColumnWithTypeAndName * NestedColumnExtractHelper::findColumn(const 
DB::Block & in_block, const std::string & name) const
 {
-    if (case_insentive)
-    {
-        std::string final_name = name;
-        boost::to_lower(final_name);
-        const auto & cols = in_block.getColumnsWithTypeAndName();
-        auto found = std::find_if(cols.begin(), cols.end(), [&](const auto & 
column) { return boost::iequals(column.name, name); });
-        if (found == cols.end())
-            return nullptr;
-        return &*found;
-    }
-
-    const auto * col = in_block.findByName(name);
-    if (col)
-        return col;
-    return nullptr;
+    return in_block.findByName(name, case_insentive);
 }
 
 const DB::ActionsDAG::Node * ActionsDAGUtil::convertNodeType(
diff --git a/cpp-ch/local-engine/Common/GlutenStringUtils.h 
b/cpp-ch/local-engine/Common/GlutenStringUtils.h
index 0d980f228f..0de185d83c 100644
--- a/cpp-ch/local-engine/Common/GlutenStringUtils.h
+++ b/cpp-ch/local-engine/Common/GlutenStringUtils.h
@@ -21,9 +21,6 @@
 
 namespace local_engine
 {
-using PartitionValue = std::pair<std::string, std::string>;
-using PartitionValues = std::vector<PartitionValue>;
-
 class GlutenStringUtils
 {
 public:
diff --git a/cpp-ch/local-engine/Operator/PartitionColumnFillingTransform.cpp 
b/cpp-ch/local-engine/Operator/PartitionColumnFillingTransform.cpp
index 724a02f5b2..ab87e1b39b 100644
--- a/cpp-ch/local-engine/Operator/PartitionColumnFillingTransform.cpp
+++ b/cpp-ch/local-engine/Operator/PartitionColumnFillingTransform.cpp
@@ -57,16 +57,11 @@ ColumnPtr createFloatPartitionColumn(DataTypePtr 
column_type, const std::string
     return column_type->createColumnConst(1, value);
 }
 
-//template <>
-//ColumnPtr createFloatPartitionColumn<Float32>(DataTypePtr column_type, 
std::string partition_value);
-//template <>
-//ColumnPtr createFloatPartitionColumn<Float64>(DataTypePtr column_type, 
std::string partition_value);
-
 PartitionColumnFillingTransform::PartitionColumnFillingTransform(
     const DB::Block & input_, const DB::Block & output_, const String & 
partition_col_name_, const String & partition_col_value_)
     : ISimpleTransform(input_, output_, true), 
partition_col_name(partition_col_name_), 
partition_col_value(partition_col_value_)
 {
-    partition_col_type = output_.getByName(partition_col_name_).type;
+    partition_col_type = output_.getByName(partition_col_name_, true).type;
     partition_column = createPartitionColumn();
 }
 
diff --git a/cpp-ch/local-engine/Parser/FunctionExecutor.cpp 
b/cpp-ch/local-engine/Parser/FunctionExecutor.cpp
index 370dc4bda9..2cef922ba4 100644
--- a/cpp-ch/local-engine/Parser/FunctionExecutor.cpp
+++ b/cpp-ch/local-engine/Parser/FunctionExecutor.cpp
@@ -79,8 +79,6 @@ void FunctionExecutor::parseExpression()
     /// Notice keep_result must be true, because result_node of current 
function must be output node in actions_dag
     const auto * node = 
expression_parser->parseFunction(expression.scalar_function(), actions_dag, 
true);
     result_name = node->result_name;
-    // std::cout << "actions_dag:" << std::endl;
-    // std::cout << actions_dag->dumpDAG() << std::endl;
 
     expression_actions = 
std::make_unique<ExpressionActions>(std::move(actions_dag));
 }
@@ -115,9 +113,7 @@ bool FunctionExecutor::executeAndCompare(const 
std::vector<FunctionExecutor::Tes
     }
     block.setColumns(std::move(columns));
 
-    // std::cout << "input block:" << block.dumpStructure() << std::endl;
     execute(block);
-    // std::cout << "output block:" << block.dumpStructure() << std::endl;
 
     const auto & result_column = block.getByName(result_name).column;
     for (size_t i = 0; i < cases.size(); ++i)
diff --git a/cpp-ch/local-engine/Parser/SerializedPlanParser.cpp 
b/cpp-ch/local-engine/Parser/SerializedPlanParser.cpp
index 4e461a5c49..42541d9d92 100644
--- a/cpp-ch/local-engine/Parser/SerializedPlanParser.cpp
+++ b/cpp-ch/local-engine/Parser/SerializedPlanParser.cpp
@@ -131,49 +131,49 @@ void SerializedPlanParser::adjustOutput(const 
DB::QueryPlanPtr & query_plan, con
     const auto & output_schema = root_rel.root().output_schema();
     if (output_schema.types_size())
     {
-        auto original_header = query_plan->getCurrentHeader();
-        const auto & original_cols = 
original_header.getColumnsWithTypeAndName();
-        if (static_cast<size_t>(output_schema.types_size()) != 
original_cols.size())
+        auto origin_header = query_plan->getCurrentHeader();
+        const auto & origin_columns = 
origin_header.getColumnsWithTypeAndName();
+
+        if (static_cast<size_t>(output_schema.types_size()) != 
origin_columns.size())
         {
             debug::dumpPlan(*query_plan, "clickhouse plan", true);
             debug::dumpMessage(plan, "substrait::Plan", true);
             throw Exception(
                 ErrorCodes::LOGICAL_ERROR,
                 "Missmatch result columns size. plan column size {}, subtrait 
plan output schema size {}, subtrait plan name size {}.",
-                original_cols.size(),
+                origin_columns.size(),
                 output_schema.types_size(),
                 root_rel.root().names_size());
         }
+
         bool need_final_project = false;
-        ColumnsWithTypeAndName final_cols;
+        ColumnsWithTypeAndName final_columns;
         for (int i = 0; i < output_schema.types_size(); ++i)
         {
-            const auto & col = original_cols[i];
-            auto type = TypeParser::parseType(output_schema.types(i));
-            // At present, we only check nullable mismatch.
-            // intermediate aggregate data is special, no check here.
-            if (type->isNullable() != col.type->isNullable() && 
!typeid_cast<const DataTypeAggregateFunction *>(col.type.get()))
-            {
-                if (type->isNullable())
-                {
-                    auto wrapped = wrapNullableType(true, col.type);
-                    final_cols.emplace_back(type->createColumn(), wrapped, 
col.name);
-                    need_final_project = !wrapped->equals(*col.type);
-                }
-                else
-                {
-                    final_cols.emplace_back(type->createColumn(), 
removeNullable(col.type), col.name);
-                    need_final_project = true;
-                }
-            }
+            const auto & origin_column = origin_columns[i];
+            const auto & origin_type = origin_column.type;
+            auto final_type = TypeParser::parseType(output_schema.types(i));
+
+            /// Intermediate aggregate data is special, no check here.
+            if (typeid_cast<const DataTypeAggregateFunction 
*>(origin_column.type.get()) || origin_type->equals(*final_type))
+                final_columns.push_back(origin_column);
             else
             {
-                final_cols.push_back(col);
+                need_final_project = true;
+
+                bool need_const = origin_column.column && 
isColumnConst(*origin_column.column);
+                ColumnWithTypeAndName final_column(
+                    need_const ? final_type->createColumnConst(0, 
assert_cast<const ColumnConst &>(*origin_column.column).getField())
+                               : final_type->createColumn(),
+                    final_type,
+                    origin_column.name);
+                final_columns.emplace_back(std::move(final_column));
             }
         }
+
         if (need_final_project)
         {
-            ActionsDAG final_project = 
ActionsDAG::makeConvertingActions(original_cols, final_cols, 
ActionsDAG::MatchColumnsMode::Position);
+            ActionsDAG final_project = 
ActionsDAG::makeConvertingActions(origin_columns, final_columns, 
ActionsDAG::MatchColumnsMode::Position);
             QueryPlanStepPtr final_project_step
                 = 
std::make_unique<ExpressionStep>(query_plan->getCurrentHeader(), 
std::move(final_project));
             final_project_step->setStepDescription("Project for output 
schema");
diff --git a/cpp-ch/local-engine/Storages/IO/NativeReader.cpp 
b/cpp-ch/local-engine/Storages/IO/NativeReader.cpp
index 48e6950e27..65c2ad8af9 100644
--- a/cpp-ch/local-engine/Storages/IO/NativeReader.cpp
+++ b/cpp-ch/local-engine/Storages/IO/NativeReader.cpp
@@ -54,6 +54,7 @@ DB::Block NativeReader::read()
     DB::Block result_block;
     if (istr.eof())
         return result_block;
+
     if (columns_parse_util.empty())
     {
         result_block = prepareByFirstBlock();
@@ -154,6 +155,7 @@ DB::Block NativeReader::prepareByFirstBlock()
 {
     if (istr.eof())
         return {};
+
     const DataTypeFactory & data_type_factory = DataTypeFactory::instance();
     DB::Block result_block;
 
@@ -246,10 +248,12 @@ bool NativeReader::appendNextBlock(DB::Block & 
result_block)
 {
     if (istr.eof())
         return false;
+
     size_t columns = 0;
     size_t rows = 0;
     readVarUInt(columns, istr);
     readVarUInt(rows, istr);
+
     for (size_t i = 0; i < columns; ++i)
     {
         // Not actually read type name.
@@ -259,6 +263,7 @@ bool NativeReader::appendNextBlock(DB::Block & result_block)
 
         if (!rows) [[unlikely]]
             continue;
+
         auto & column_parse_util = columns_parse_util[i];
         auto & column = result_block.getByPosition(i);
         column_parse_util.parse(istr, column.column, rows, column_parse_util);
diff --git a/cpp-ch/local-engine/Storages/IO/NativeWriter.cpp 
b/cpp-ch/local-engine/Storages/IO/NativeWriter.cpp
index 7f09721abb..c19005cd13 100644
--- a/cpp-ch/local-engine/Storages/IO/NativeWriter.cpp
+++ b/cpp-ch/local-engine/Storages/IO/NativeWriter.cpp
@@ -32,6 +32,7 @@ namespace local_engine
 {
 
 const String NativeWriter::AGG_STATE_SUFFIX= "#optagg";
+
 void NativeWriter::flush()
 {
     ostr.next();
diff --git a/cpp-ch/local-engine/Storages/SubstraitSource/FormatFile.cpp 
b/cpp-ch/local-engine/Storages/SubstraitSource/FormatFile.cpp
index fc5acc533d..3c68c70e66 100644
--- a/cpp-ch/local-engine/Storages/SubstraitSource/FormatFile.cpp
+++ b/cpp-ch/local-engine/Storages/SubstraitSource/FormatFile.cpp
@@ -19,10 +19,12 @@
 #include <Core/Settings.h>
 #include <IO/ReadBufferFromFile.h>
 #include <Storages/SubstraitSource/JSONFormatFile.h>
+#include <boost/algorithm/string/case_conv.hpp>
 #include <Common/GlutenConfig.h>
 #include <Common/GlutenStringUtils.h>
 #include <Common/logger_useful.h>
 
+
 #if USE_PARQUET
 #include <Storages/SubstraitSource/ParquetFormatFile.h>
 #endif
@@ -56,13 +58,18 @@ FormatFile::FormatFile(
         for (size_t i = 0; i < file_info.partition_columns_size(); ++i)
         {
             const auto & partition_column = file_info.partition_columns(i);
+
             std::string unescaped_key;
             std::string unescaped_value;
             Poco::URI::decode(partition_column.key(), unescaped_key);
             Poco::URI::decode(partition_column.value(), unescaped_value);
-            auto key = std::move(unescaped_key);
-            partition_keys.push_back(key);
-            partition_values[key] = std::move(unescaped_value);
+
+            partition_keys.push_back(unescaped_key);
+            partition_values[unescaped_key] = unescaped_value;
+
+            std::string normalized_key = unescaped_key;
+            boost::to_lower(normalized_key);
+            normalized_partition_values[normalized_key] = unescaped_value;
         }
     }
 
diff --git a/cpp-ch/local-engine/Storages/SubstraitSource/FormatFile.h 
b/cpp-ch/local-engine/Storages/SubstraitSource/FormatFile.h
index 14b53f6842..f93abd916b 100644
--- a/cpp-ch/local-engine/Storages/SubstraitSource/FormatFile.h
+++ b/cpp-ch/local-engine/Storages/SubstraitSource/FormatFile.h
@@ -65,9 +65,11 @@ public:
     virtual std::optional<size_t> getTotalRows() { return {}; }
 
     /// Get partition keys from file path
-    inline const std::vector<String> & getFilePartitionKeys() const { return 
partition_keys; }
+    const std::vector<String> & getFilePartitionKeys() const { return 
partition_keys; }
 
-    inline const std::map<String, String> & getFilePartitionValues() const { 
return partition_values; }
+    const std::map<String, String> & getFilePartitionValues() const { return 
partition_values; }
+
+    const std::map<String, String> & getFileNormalizedPartitionValues() const 
{ return normalized_partition_values; }
 
     virtual String getURIPath() const { return file_info.uri_file(); }
 
@@ -81,6 +83,8 @@ protected:
     ReadBufferBuilderPtr read_buffer_builder;
     std::vector<String> partition_keys;
     std::map<String, String> partition_values;
+    /// partition keys are normalized to lower cases for partition column 
case-insensitive matching
+    std::map<String, String> normalized_partition_values;
     std::shared_ptr<const DB::KeyCondition> key_condition;
 };
 using FormatFilePtr = std::shared_ptr<FormatFile>;
diff --git 
a/cpp-ch/local-engine/Storages/SubstraitSource/SubstraitFileSource.cpp 
b/cpp-ch/local-engine/Storages/SubstraitSource/SubstraitFileSource.cpp
index ffe1d18ae7..ef350472b6 100644
--- a/cpp-ch/local-engine/Storages/SubstraitSource/SubstraitFileSource.cpp
+++ b/cpp-ch/local-engine/Storages/SubstraitSource/SubstraitFileSource.cpp
@@ -17,6 +17,7 @@
 #include <functional>
 #include <memory>
 
+#include <boost/algorithm/string/case_conv.hpp>
 #include <substrait/plan.pb.h>
 #include <magic_enum.hpp>
 #include <Poco/URI.h>
@@ -87,8 +88,8 @@ SubstraitFileSource::SubstraitFileSource(
         /// File partition keys are read from the file path
         const auto partition_keys = files[0]->getFilePartitionKeys();
         for (const auto & key : partition_keys)
-            if (to_read_header.findByName(key))
-                to_read_header.erase(key);
+            if (const auto * col = to_read_header.findByName(key, true))
+                to_read_header.erase(col->name);
     }
 }
 
@@ -337,14 +338,15 @@ bool ConstColumnsFileReader::pull(DB::Chunk & chunk)
     if (const size_t col_num = header.columns())
     {
         res_columns.reserve(col_num);
-        const auto & partition_values = file->getFilePartitionValues();
+        const auto & normalized_partition_values = 
file->getFileNormalizedPartitionValues();
         for (size_t pos = 0; pos < col_num; ++pos)
         {
-            auto col_with_name_and_type = header.getByPosition(pos);
-            auto type = col_with_name_and_type.type;
-            const auto & name = col_with_name_and_type.name;
-            auto it = partition_values.find(name);
-            if (it == partition_values.end())
+            const auto & column = header.getByPosition(pos);
+            const auto & type = column.type;
+            const auto & name = column.name;
+
+            auto it = 
normalized_partition_values.find(boost::to_lower_copy(name));
+            if (it == normalized_partition_values.end())
                 throw DB::Exception(DB::ErrorCodes::LOGICAL_ERROR, "Unknow 
partition column : {}", name);
 
             res_columns.emplace_back(createColumn(it->second, type, 
to_read_rows));
@@ -377,13 +379,13 @@ bool NormalFileReader::pull(DB::Chunk & chunk)
     if (!rows)
         return false;
 
-    const auto read_columns = raw_chunk.detachColumns();
-    auto columns_with_name_and_type = 
output_header.getColumnsWithTypeAndName();
-    auto partition_values = file->getFilePartitionValues();
+    auto read_columns = raw_chunk.detachColumns();
+    const auto & columns = output_header.getColumnsWithTypeAndName();
+    const auto & normalized_partition_values = 
file->getFileNormalizedPartitionValues();
 
     DB::Columns res_columns;
-    res_columns.reserve(columns_with_name_and_type.size());
-    for (auto & column : columns_with_name_and_type)
+    res_columns.reserve(columns.size());
+    for (auto & column : columns)
     {
         if (to_read_header.has(column.name))
         {
@@ -392,12 +394,11 @@ bool NormalFileReader::pull(DB::Chunk & chunk)
         }
         else
         {
-            auto it = partition_values.find(column.name);
-            if (it == partition_values.end())
-            {
+            auto it = 
normalized_partition_values.find(boost::to_lower_copy(column.name));
+            if (it == normalized_partition_values.end())
                 throw DB::Exception(
                     DB::ErrorCodes::LOGICAL_ERROR, "Not found column({}) from 
file({}) partition keys.", column.name, file->getURIPath());
-            }
+
             res_columns.push_back(createColumn(it->second, column.type, rows));
         }
     }
diff --git 
a/gluten-ut/spark32/src/test/scala/org/apache/gluten/utils/clickhouse/ClickHouseTestSettings.scala
 
b/gluten-ut/spark32/src/test/scala/org/apache/gluten/utils/clickhouse/ClickHouseTestSettings.scala
index 50110f15d4..2eb5bd11ff 100644
--- 
a/gluten-ut/spark32/src/test/scala/org/apache/gluten/utils/clickhouse/ClickHouseTestSettings.scala
+++ 
b/gluten-ut/spark32/src/test/scala/org/apache/gluten/utils/clickhouse/ClickHouseTestSettings.scala
@@ -203,6 +203,9 @@ class ClickHouseTestSettings extends BackendTestSettings {
     .exclude(
       "SPARK-32376: Make unionByName null-filling behavior work with struct 
columns - deep expr")
     .exclude("SPARK-35756: unionByName support struct having same col names 
but different sequence")
+    .exclude(
+      "SPARK-36673: Only merge nullability for Unions of struct"
+    ) // disabled due to case-insensitive not supported in CH tuple
     .exclude("except all")
     .exclude("exceptAll - nullability")
     .exclude("intersectAll")
diff --git 
a/gluten-ut/spark33/src/test/scala/org/apache/gluten/utils/clickhouse/ClickHouseTestSettings.scala
 
b/gluten-ut/spark33/src/test/scala/org/apache/gluten/utils/clickhouse/ClickHouseTestSettings.scala
index 9b3b090e32..a7bf5d4da9 100644
--- 
a/gluten-ut/spark33/src/test/scala/org/apache/gluten/utils/clickhouse/ClickHouseTestSettings.scala
+++ 
b/gluten-ut/spark33/src/test/scala/org/apache/gluten/utils/clickhouse/ClickHouseTestSettings.scala
@@ -225,6 +225,9 @@ class ClickHouseTestSettings extends BackendTestSettings {
     .exclude("SPARK-35756: unionByName support struct having same col names 
but different sequence")
     .exclude("SPARK-36797: Union should resolve nested columns as top-level 
columns")
     .exclude("SPARK-37371: UnionExec should support columnar if all children 
support columnar")
+    .exclude(
+      "SPARK-36673: Only merge nullability for Unions of struct"
+    ) // disabled due to case-insensitive not supported in CH tuple
     .exclude("except all")
     .exclude("exceptAll - nullability")
     .exclude("intersectAll")
diff --git 
a/gluten-ut/spark34/src/test/scala/org/apache/gluten/utils/clickhouse/ClickHouseTestSettings.scala
 
b/gluten-ut/spark34/src/test/scala/org/apache/gluten/utils/clickhouse/ClickHouseTestSettings.scala
index e91f1495fb..fe96e0abde 100644
--- 
a/gluten-ut/spark34/src/test/scala/org/apache/gluten/utils/clickhouse/ClickHouseTestSettings.scala
+++ 
b/gluten-ut/spark34/src/test/scala/org/apache/gluten/utils/clickhouse/ClickHouseTestSettings.scala
@@ -227,6 +227,9 @@ class ClickHouseTestSettings extends BackendTestSettings {
     .exclude("SPARK-35756: unionByName support struct having same col names 
but different sequence")
     .exclude("SPARK-36797: Union should resolve nested columns as top-level 
columns")
     .exclude("SPARK-37371: UnionExec should support columnar if all children 
support columnar")
+    .exclude(
+      "SPARK-36673: Only merge nullability for Unions of struct"
+    ) // disabled due to case-insensitive not supported in CH tuple
   enableSuite[GlutenDataFrameStatSuite]
   enableSuite[GlutenDataFrameSuite]
     .exclude("Uuid expressions should produce same results at retries in the 
same DataFrame")
diff --git 
a/gluten-ut/spark35/src/test/scala/org/apache/gluten/utils/clickhouse/ClickHouseTestSettings.scala
 
b/gluten-ut/spark35/src/test/scala/org/apache/gluten/utils/clickhouse/ClickHouseTestSettings.scala
index f0637839a7..cf5122fb66 100644
--- 
a/gluten-ut/spark35/src/test/scala/org/apache/gluten/utils/clickhouse/ClickHouseTestSettings.scala
+++ 
b/gluten-ut/spark35/src/test/scala/org/apache/gluten/utils/clickhouse/ClickHouseTestSettings.scala
@@ -227,6 +227,9 @@ class ClickHouseTestSettings extends BackendTestSettings {
     .exclude("SPARK-35756: unionByName support struct having same col names 
but different sequence")
     .exclude("SPARK-36797: Union should resolve nested columns as top-level 
columns")
     .exclude("SPARK-37371: UnionExec should support columnar if all children 
support columnar")
+    .exclude(
+      "SPARK-36673: Only merge nullability for Unions of struct"
+    ) // disabled due to case-insensitive not supported in CH tuple
   enableSuite[GlutenDataFrameStatSuite]
   enableSuite[GlutenDataFrameSuite]
     .exclude("Uuid expressions should produce same results at retries in the 
same DataFrame")


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

Reply via email to