Merge pull request #70494 from ClickHouse/backport/24.8/70374

Backport #70374 to 24.8: Fix crash during GROUP BY JSON sub-object subcolumn
This commit is contained in:
Pavel Kruglov 2024-10-29 11:23:44 +01:00 committed by GitHub
commit eba9ddef43
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 29 additions and 7 deletions

View File

@ -323,6 +323,19 @@ void ColumnObject::setDynamicPaths(const std::vector<String> & paths)
} }
} }
void ColumnObject::setDynamicPaths(const std::vector<std::pair<String, ColumnPtr>> & paths)
{
if (paths.size() > max_dynamic_paths)
throw Exception(ErrorCodes::LOGICAL_ERROR, "Cannot set dynamic paths to Object column, the number of paths ({}) exceeds the limit ({})", paths.size(), max_dynamic_paths);
for (const auto & [path, column] : paths)
{
auto it = dynamic_paths.emplace(path, column).first;
dynamic_paths_ptrs[path] = assert_cast<ColumnDynamic *>(it->second.get());
sorted_dynamic_paths.insert(it->first);
}
}
void ColumnObject::insert(const Field & x) void ColumnObject::insert(const Field & x)
{ {
const auto & object = x.safeGet<Object>(); const auto & object = x.safeGet<Object>();

View File

@ -222,6 +222,7 @@ public:
void addNewDynamicPath(std::string_view path); void addNewDynamicPath(std::string_view path);
void setDynamicPaths(const std::vector<String> & paths); void setDynamicPaths(const std::vector<String> & paths);
void setDynamicPaths(const std::vector<std::pair<String, ColumnPtr>> & paths);
void setMaxDynamicPaths(size_t max_dynamic_paths_); void setMaxDynamicPaths(size_t max_dynamic_paths_);
void setStatistics(const StatisticsPtr & statistics_) { statistics = statistics_; } void setStatistics(const StatisticsPtr & statistics_) { statistics = statistics_; }

View File

@ -348,17 +348,13 @@ std::unique_ptr<ISerialization::SubstreamData> DataTypeObject::getDynamicSubcolu
result_typed_columns[getSubPath(path, prefix)] = column; result_typed_columns[getSubPath(path, prefix)] = column;
} }
auto & result_dynamic_columns = result_object_column.getDynamicPaths(); std::vector<std::pair<String, ColumnPtr>> result_dynamic_paths;
auto & result_dynamic_columns_ptrs = result_object_column.getDynamicPathsPtrs();
for (const auto & [path, column] : object_column.getDynamicPaths()) for (const auto & [path, column] : object_column.getDynamicPaths())
{ {
if (path.starts_with(prefix) && path.size() != prefix.size()) if (path.starts_with(prefix) && path.size() != prefix.size())
{ result_dynamic_paths.emplace_back(getSubPath(path, prefix), column);
auto sub_path = getSubPath(path, prefix);
result_dynamic_columns[sub_path] = column;
result_dynamic_columns_ptrs[sub_path] = assert_cast<ColumnDynamic *>(result_dynamic_columns[sub_path].get());
}
} }
result_object_column.setDynamicPaths(result_dynamic_paths);
const auto & shared_data_offsets = object_column.getSharedDataOffsets(); const auto & shared_data_offsets = object_column.getSharedDataOffsets();
const auto [shared_data_paths, shared_data_values] = object_column.getSharedDataPathsAndValues(); const auto [shared_data_paths, shared_data_values] = object_column.getSharedDataPathsAndValues();

View File

@ -0,0 +1,2 @@
{"b":{"c":0,"d":"0","e":"str_0"}}
{"b":{"c":0,"d":"1","e":"str_1"}}

View File

@ -0,0 +1,10 @@
set allow_experimental_json_type = 1;
set allow_experimental_variant_type = 1;
set use_variant_as_common_type = 1;
drop table if exists test;
create table test (json JSON(max_dynamic_paths = 20, `a.b.c` UInt32)) engine = Memory;
insert into test select toJSONString(map('a.b.d', number::UInt32, 'a.b.e', 'str_' || toString(number))) from numbers(2);
select json.^a from test group by json.^a order by toString(json.^a);
drop table test;