ClickHouse/src/Planner/PlannerSorting.cpp

157 lines
5.9 KiB
C++
Raw Normal View History

2022-08-26 13:06:14 +00:00
#include <Planner/PlannerSorting.h>
#include <Common/FieldVisitorsAccurateComparison.h>
#include <DataTypes/DataTypeInterval.h>
#include <Interpreters/Context.h>
#include <Analyzer/ConstantNode.h>
2022-09-15 11:25:11 +00:00
#include <Analyzer/SortNode.h>
2022-08-26 13:06:14 +00:00
#include <Planner/PlannerActionsVisitor.h>
namespace DB
{
namespace ErrorCodes
{
extern const int INVALID_WITH_FILL_EXPRESSION;
}
namespace
{
std::pair<Field, DataTypePtr> extractWithFillValue(const QueryTreeNodePtr & node)
{
2022-08-31 15:21:17 +00:00
auto constant_value = node->getConstantValue();
2022-08-26 13:06:14 +00:00
std::pair<Field, DataTypePtr> result;
2022-08-31 15:21:17 +00:00
result.first = constant_value.getValue();
result.second = constant_value.getType();
2022-08-26 13:06:14 +00:00
if (!isColumnedAsNumber(result.second))
throw Exception(ErrorCodes::INVALID_WITH_FILL_EXPRESSION, "WITH FILL expression must be constant with numeric type");
return result;
}
std::pair<Field, std::optional<IntervalKind>> extractWithFillStepValue(const QueryTreeNodePtr & node)
{
2022-08-31 15:21:17 +00:00
auto constant_value = node->getConstantValue();
const auto & constant_node_result_type = constant_value.getType();
2022-08-26 13:06:14 +00:00
if (const auto * type_interval = typeid_cast<const DataTypeInterval *>(constant_node_result_type.get()))
2022-08-31 15:21:17 +00:00
return std::make_pair(constant_value.getValue(), type_interval->getKind());
2022-08-26 13:06:14 +00:00
if (!isColumnedAsNumber(constant_node_result_type))
throw Exception(ErrorCodes::INVALID_WITH_FILL_EXPRESSION, "WITH FILL expression must be constant with numeric type");
2022-08-31 15:21:17 +00:00
return {constant_value.getValue(), {}};
2022-08-26 13:06:14 +00:00
}
2022-09-15 11:25:11 +00:00
FillColumnDescription extractWithFillDescription(const SortNode & sort_node)
2022-08-26 13:06:14 +00:00
{
FillColumnDescription fill_column_description;
2022-09-15 11:25:11 +00:00
if (sort_node.hasFillFrom())
2022-08-26 13:06:14 +00:00
{
2022-09-15 11:25:11 +00:00
auto extract_result = extractWithFillValue(sort_node.getFillFrom());
2022-08-26 13:06:14 +00:00
fill_column_description.fill_from = std::move(extract_result.first);
fill_column_description.fill_from_type = std::move(extract_result.second);
}
2022-09-15 11:25:11 +00:00
if (sort_node.hasFillTo())
2022-08-26 13:06:14 +00:00
{
2022-09-15 11:25:11 +00:00
auto extract_result = extractWithFillValue(sort_node.getFillTo());
2022-08-26 13:06:14 +00:00
fill_column_description.fill_to = std::move(extract_result.first);
fill_column_description.fill_to_type = std::move(extract_result.second);
}
2022-09-15 11:25:11 +00:00
if (sort_node.hasFillStep())
2022-08-26 13:06:14 +00:00
{
2022-09-15 11:25:11 +00:00
auto extract_result = extractWithFillStepValue(sort_node.getFillStep());
2022-08-26 13:06:14 +00:00
fill_column_description.fill_step = std::move(extract_result.first);
fill_column_description.step_kind = std::move(extract_result.second);
}
else
{
2022-09-15 11:25:11 +00:00
fill_column_description.fill_step = Field(sort_node.getSortDirection() == SortDirection::ASCENDING ? 1 : -1);
2022-08-26 13:06:14 +00:00
}
if (applyVisitor(FieldVisitorAccurateEquals(), fill_column_description.fill_step, Field{0}))
throw Exception(ErrorCodes::INVALID_WITH_FILL_EXPRESSION,
"WITH FILL STEP value cannot be zero");
2022-09-15 11:25:11 +00:00
if (sort_node.getSortDirection() == SortDirection::ASCENDING)
2022-08-26 13:06:14 +00:00
{
if (applyVisitor(FieldVisitorAccurateLess(), fill_column_description.fill_step, Field{0}))
throw Exception(ErrorCodes::INVALID_WITH_FILL_EXPRESSION,
"WITH FILL STEP value cannot be negative for sorting in ascending direction");
if (!fill_column_description.fill_from.isNull() && !fill_column_description.fill_to.isNull() &&
applyVisitor(FieldVisitorAccurateLess(), fill_column_description.fill_to, fill_column_description.fill_from))
{
throw Exception(ErrorCodes::INVALID_WITH_FILL_EXPRESSION,
"WITH FILL TO value cannot be less than FROM value for sorting in ascending direction");
}
}
else
{
if (applyVisitor(FieldVisitorAccurateLess(), Field{0}, fill_column_description.fill_step))
throw Exception(ErrorCodes::INVALID_WITH_FILL_EXPRESSION,
"WITH FILL STEP value cannot be positive for sorting in descending direction");
if (!fill_column_description.fill_from.isNull() && !fill_column_description.fill_to.isNull() &&
applyVisitor(FieldVisitorAccurateLess(), fill_column_description.fill_from, fill_column_description.fill_to))
{
throw Exception(ErrorCodes::INVALID_WITH_FILL_EXPRESSION,
"WITH FILL FROM value cannot be less than TO value for sorting in descending direction");
}
}
return fill_column_description;
}
}
SortDescription extractSortDescription(const QueryTreeNodePtr & order_by_node, const PlannerContext & planner_context)
{
auto & order_by_list_node = order_by_node->as<ListNode &>();
SortDescription sort_column_description;
sort_column_description.reserve(order_by_list_node.getNodes().size());
2022-09-15 11:25:11 +00:00
for (const auto & sort_node : order_by_list_node.getNodes())
2022-08-26 13:06:14 +00:00
{
2022-09-15 11:25:11 +00:00
auto & sort_node_typed = sort_node->as<SortNode &>();
2022-08-26 13:06:14 +00:00
2022-09-15 11:25:11 +00:00
auto column_name = calculateActionNodeName(sort_node_typed.getExpression(), planner_context);
std::shared_ptr<Collator> collator = sort_node_typed.getCollator();
int direction = sort_node_typed.getSortDirection() == SortDirection::ASCENDING ? 1 : -1;
2022-08-26 13:06:14 +00:00
int nulls_direction = direction;
2022-09-15 11:25:11 +00:00
auto nulls_sort_direction = sort_node_typed.getNullsSortDirection();
2022-08-26 13:06:14 +00:00
if (nulls_sort_direction)
nulls_direction = *nulls_sort_direction == SortDirection::ASCENDING ? 1 : -1;
2022-09-15 11:25:11 +00:00
if (sort_node_typed.withFill())
2022-08-26 13:06:14 +00:00
{
2022-09-15 11:25:11 +00:00
FillColumnDescription fill_description = extractWithFillDescription(sort_node_typed);
2022-08-26 13:06:14 +00:00
sort_column_description.emplace_back(column_name, direction, nulls_direction, collator, true /*with_fill*/, fill_description);
}
else
{
sort_column_description.emplace_back(column_name, direction, nulls_direction, collator);
}
}
const auto & settings = planner_context.getQueryContext()->getSettingsRef();
sort_column_description.compile_sort_description = settings.compile_sort_description;
sort_column_description.min_count_to_compile_sort_description = settings.min_count_to_compile_sort_description;
return sort_column_description;
}
}