#include "optimizer/remove_unnecessary_order_by_optimizer.h"
#include "planner/operator/logical_aggregate.h"
#include "planner/operator/logical_limit.h"
#include "planner/operator/logical_order_by.h"
#include "planner/operator/logical_projection.h"
using namespace lbug::common;
using namespace lbug::planner;
namespace lbug {
namespace optimizer {
void RemoveUnnecessaryOrderByOptimizer::rewrite(LogicalPlan* plan) {
plan->setLastOperator(visitOperator(plan->getLastOperator()));
}
std::shared_ptr<planner::LogicalOperator> RemoveUnnecessaryOrderByOptimizer::visitOperator(
std::shared_ptr<planner::LogicalOperator> op) {
for (auto i = 0u; i < op->getNumChildren(); ++i) {
op->setChild(i, visitOperator(op->getChild(i)));
}
auto result = tryRemoveOrderByFromAggregate(std::move(op));
result->computeFactorizedSchema();
return result;
}
std::shared_ptr<planner::LogicalOperator>
RemoveUnnecessaryOrderByOptimizer::tryRemoveOrderByFromAggregate(
std::shared_ptr<planner::LogicalOperator> op) {
if (op->getOperatorType() != LogicalOperatorType::AGGREGATE) {
return op;
}
auto& aggregate = op->cast<LogicalAggregate>();
if (aggregate.hasKeys()) {
return op;
}
bool changed = false;
auto newChild = stripOrderByBelow(op->getChild(0), changed);
if (changed) {
op->setChild(0, std::move(newChild));
}
return op;
}
std::shared_ptr<planner::LogicalOperator> RemoveUnnecessaryOrderByOptimizer::stripOrderByBelow(
std::shared_ptr<planner::LogicalOperator> op, bool& changed) {
switch (op->getOperatorType()) {
case LogicalOperatorType::ORDER_BY: {
auto& orderBy = op->cast<LogicalOrderBy>();
auto grandChild = orderBy.getChild(0);
std::shared_ptr<planner::LogicalOperator> replacement;
if (orderBy.hasLimitNum()) {
auto limitExpr = orderBy.getLimitNum();
auto skipExpr = orderBy.hasSkipNum() ? orderBy.getSkipNum() : nullptr;
auto limitOp = std::make_shared<LogicalLimit>(skipExpr, limitExpr, grandChild);
limitOp->computeFactorizedSchema();
replacement = std::move(limitOp);
} else {
replacement = grandChild;
}
changed = true;
return replacement;
}
case LogicalOperatorType::PROJECTION:
case LogicalOperatorType::MULTIPLICITY_REDUCER:
case LogicalOperatorType::LIMIT:
case LogicalOperatorType::FILTER: {
if (op->getNumChildren() != 1) {
return op;
}
bool childChanged = false;
auto newChild = stripOrderByBelow(op->getChild(0), childChanged);
if (childChanged) {
op->setChild(0, std::move(newChild));
op->computeFactorizedSchema();
changed = true;
}
return op;
}
default:
return op;
}
}
} }