Merge pull request #126273 from ClickHouse/simplify_key_description

Simplify sorting description parsing
This commit is contained in:
Konstantin Vedernikov authored and GitHub committed 2026-10-18 20:19:56 +00:00
commit 94e0f5acdc
1 file changed
+60 -60
@@ -1797,6 +1797,21 @@ KeyDescription getSortingKeyDescriptionFromMetadata(Poco::JSON::Object::Ptr meta
{
auto sort_order_id = metadata_object->getValue<Int64>(f_default_sort_order_id);
Poco::JSON::Array::Ptr sort_orders = metadata_object->getArray(f_sort_orders);
Poco::JSON::Array::Ptr fields;
for (UInt32 i = 0; i < sort_orders->size(); ++i)
{
auto sort_order = sort_orders->getObject(i);
if (sort_order->getValue<Int64>(f_order_id) == sort_order_id)
{
fields = sort_order->getArray(f_fields);
break;
}
}
if (!fields || fields->size() == 0)
return KeyDescription{};
std::unordered_map<Int64, String> source_id_to_column_name;
auto [schema, current_schema_id] = parseTableSchemaV2Method(metadata_object);
@@ -1806,70 +1821,55 @@ KeyDescription getSortingKeyDescriptionFromMetadata(Poco::JSON::Object::Ptr meta
source_id_to_column_name[source_id] = col_name;
}
KeyDescription key_description;
ColumnsDescription column_description;
for (size_t i = 0; i < ch_schema.size(); ++i)
column_description.add(ColumnDescription(ch_schema.getNames()[i], ch_schema.getTypes()[i]));
String order_by_str;
for (UInt32 i = 0; i < sort_orders->size(); ++i)
for (UInt32 field_index = 0; field_index < fields->size(); ++field_index)
{
auto sort_order = sort_orders->getObject(i);
if (sort_order->getValue<Int64>(f_order_id) != sort_order_id)
continue;
auto fields = sort_order->getArray(f_fields);
for (UInt32 field_index = 0; field_index < fields->size(); ++field_index)
auto field = fields->getObject(field_index);
auto source_id = field->getValue<Int64>(f_source_id);
auto column_name = source_id_to_column_name[source_id];
int direction = field->getValue<String>(f_direction) == "asc" ? 1 : -1;
auto iceberg_transform_name = field->getValue<String>(f_transform);
std::optional<TransformAndArgument> clickhouse_transform_name;
try
{
auto field = fields->getObject(field_index);
auto source_id = field->getValue<Int64>(f_source_id);
auto column_name = source_id_to_column_name[source_id];
int direction = field->getValue<String>(f_direction) == "asc" ? 1 : -1;
auto iceberg_transform_name = field->getValue<String>(f_transform);
std::optional<TransformAndArgument> clickhouse_transform_name;
try
{
clickhouse_transform_name = parseTransformAndArgument(iceberg_transform_name);
}
catch (const Exception & e)
{
if (e.code() != ErrorCodes::BAD_ARGUMENTS)
throw;
}
if (!clickhouse_transform_name.has_value())
{
/// An unknown or malformed transform is not a reason to reject the table: an Iceberg
/// sort order is only an optimization hint, so drop it and read/write the table as unsorted.
return KeyDescription{};
}
/// Quote the column name so identifiers with special characters (e.g. `@timestamp`)
/// produce a parseable ORDER BY clause.
auto quoted_column_name = backQuoteIfNeed(column_name);
String full_argument;
if (clickhouse_transform_name->transform_name != "identity")
{
full_argument = clickhouse_transform_name->transform_name + "(";
if (clickhouse_transform_name->argument)
{
full_argument += std::to_string(*clickhouse_transform_name->argument) + ", ";
}
full_argument += quoted_column_name + ")";
}
else
{
full_argument = quoted_column_name;
}
if (direction == 1)
order_by_str += fmt::format("{} ASC,", full_argument);
else
order_by_str += fmt::format("{} DESC,", full_argument);
clickhouse_transform_name = parseTransformAndArgument(iceberg_transform_name);
}
break;
catch (const Exception & e)
{
if (e.code() != ErrorCodes::BAD_ARGUMENTS)
throw;
}
if (!clickhouse_transform_name.has_value())
{
/// An unknown or malformed transform is not a reason to reject the table: an Iceberg
/// sort order is only an optimization hint, so drop it and read/write the table as unsorted.
return KeyDescription{};
}
/// Quote the column name so identifiers with special characters (e.g. `@timestamp`)
/// produce a parseable ORDER BY clause.
auto quoted_column_name = backQuoteIfNeed(column_name);
String full_argument;
if (clickhouse_transform_name->transform_name != "identity")
{
full_argument = clickhouse_transform_name->transform_name + "(";
if (clickhouse_transform_name->argument)
{
full_argument += std::to_string(*clickhouse_transform_name->argument) + ", ";
}
full_argument += quoted_column_name + ")";
}
else
{
full_argument = quoted_column_name;
}
if (direction == 1)
order_by_str += fmt::format("{} ASC,", full_argument);
else
order_by_str += fmt::format("{} DESC,", full_argument);
}
if (order_by_str.empty())
return KeyDescription{};
order_by_str.pop_back();
return KeyDescription::parse(order_by_str, column_description, {}, local_context, true);
return KeyDescription::parse(order_by_str, ColumnsDescription(ch_schema), {}, local_context, true);
}
DataTypePtr getFunctionResultType(const String & iceberg_transform_name, DataTypePtr source_type)
@@ -1897,9 +1897,9 @@ void sortBlockByKeyDescription(Block & block, const KeyDescription & sort_descri
ColumnsWithTypeAndName reordered_columns;
for (const auto & column_name : initial_column_names)
reordered_columns.push_back(block.getByName(column_name));
for (size_t i = 0; i < block.columns(); ++i)
if (!initial_column_names_set.contains(block.getNames()[i]))
reordered_columns.push_back(block.getColumnsWithTypeAndName()[i]);
for (const auto & column : block.getColumnsWithTypeAndName())
if (!initial_column_names_set.contains(column.name))
reordered_columns.push_back(column);
block = Block(reordered_columns);
SortDescription result_sort_description;