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]