Current section
Files
Jump to
Current section
Files
c_src/duckdb/src/planner/logical_operator_visitor.cpp
#include "duckdb/planner/logical_operator_visitor.hpp"
#include "duckdb/planner/expression/list.hpp"
#include "duckdb/planner/expression_iterator.hpp"
#include "duckdb/planner/operator/list.hpp"
namespace duckdb {
void LogicalOperatorVisitor::VisitOperator(LogicalOperator &op) {
VisitOperatorChildren(op);
VisitOperatorExpressions(op);
}
void LogicalOperatorVisitor::VisitOperatorChildren(LogicalOperator &op) {
for (auto &child : op.children) {
VisitOperator(*child);
}
}
void LogicalOperatorVisitor::EnumerateExpressions(LogicalOperator &op,
const std::function<void(unique_ptr<Expression> *child)> &callback) {
switch (op.type) {
case LogicalOperatorType::LOGICAL_EXPRESSION_GET: {
auto &get = (LogicalExpressionGet &)op;
for (auto &expr_list : get.expressions) {
for (auto &expr : expr_list) {
callback(&expr);
}
}
break;
}
case LogicalOperatorType::LOGICAL_ORDER_BY: {
auto &order = (LogicalOrder &)op;
for (auto &node : order.orders) {
callback(&node.expression);
}
break;
}
case LogicalOperatorType::LOGICAL_TOP_N: {
auto &order = (LogicalTopN &)op;
for (auto &node : order.orders) {
callback(&node.expression);
}
break;
}
case LogicalOperatorType::LOGICAL_DISTINCT: {
auto &distinct = (LogicalDistinct &)op;
for (auto &target : distinct.distinct_targets) {
callback(&target);
}
break;
}
case LogicalOperatorType::LOGICAL_DELIM_JOIN:
case LogicalOperatorType::LOGICAL_COMPARISON_JOIN: {
if (op.type == LogicalOperatorType::LOGICAL_DELIM_JOIN) {
auto &delim_join = (LogicalDelimJoin &)op;
for (auto &expr : delim_join.duplicate_eliminated_columns) {
callback(&expr);
}
}
auto &join = (LogicalComparisonJoin &)op;
for (auto &cond : join.conditions) {
callback(&cond.left);
callback(&cond.right);
}
break;
}
case LogicalOperatorType::LOGICAL_ANY_JOIN: {
auto &join = (LogicalAnyJoin &)op;
callback(&join.condition);
break;
}
case LogicalOperatorType::LOGICAL_LIMIT: {
auto &limit = (LogicalLimit &)op;
if (limit.limit) {
callback(&limit.limit);
}
if (limit.offset) {
callback(&limit.offset);
}
break;
}
case LogicalOperatorType::LOGICAL_AGGREGATE_AND_GROUP_BY: {
auto &aggr = (LogicalAggregate &)op;
for (auto &group : aggr.groups) {
callback(&group);
}
break;
}
default:
break;
}
for (auto &expression : op.expressions) {
callback(&expression);
}
}
void LogicalOperatorVisitor::VisitOperatorExpressions(LogicalOperator &op) {
LogicalOperatorVisitor::EnumerateExpressions(op, [&](unique_ptr<Expression> *child) { VisitExpression(child); });
}
void LogicalOperatorVisitor::VisitExpression(unique_ptr<Expression> *expression) {
auto &expr = **expression;
unique_ptr<Expression> result;
switch (expr.GetExpressionClass()) {
case ExpressionClass::BOUND_AGGREGATE:
result = VisitReplace((BoundAggregateExpression &)expr, expression);
break;
case ExpressionClass::BOUND_BETWEEN:
result = VisitReplace((BoundBetweenExpression &)expr, expression);
break;
case ExpressionClass::BOUND_CASE:
result = VisitReplace((BoundCaseExpression &)expr, expression);
break;
case ExpressionClass::BOUND_CAST:
result = VisitReplace((BoundCastExpression &)expr, expression);
break;
case ExpressionClass::BOUND_COLUMN_REF:
result = VisitReplace((BoundColumnRefExpression &)expr, expression);
break;
case ExpressionClass::BOUND_COMPARISON:
result = VisitReplace((BoundComparisonExpression &)expr, expression);
break;
case ExpressionClass::BOUND_CONJUNCTION:
result = VisitReplace((BoundConjunctionExpression &)expr, expression);
break;
case ExpressionClass::BOUND_CONSTANT:
result = VisitReplace((BoundConstantExpression &)expr, expression);
break;
case ExpressionClass::BOUND_FUNCTION:
result = VisitReplace((BoundFunctionExpression &)expr, expression);
break;
case ExpressionClass::BOUND_SUBQUERY:
result = VisitReplace((BoundSubqueryExpression &)expr, expression);
break;
case ExpressionClass::BOUND_OPERATOR:
result = VisitReplace((BoundOperatorExpression &)expr, expression);
break;
case ExpressionClass::BOUND_PARAMETER:
result = VisitReplace((BoundParameterExpression &)expr, expression);
break;
case ExpressionClass::BOUND_REF:
result = VisitReplace((BoundReferenceExpression &)expr, expression);
break;
case ExpressionClass::BOUND_DEFAULT:
result = VisitReplace((BoundDefaultExpression &)expr, expression);
break;
case ExpressionClass::BOUND_WINDOW:
result = VisitReplace((BoundWindowExpression &)expr, expression);
break;
case ExpressionClass::BOUND_UNNEST:
result = VisitReplace((BoundUnnestExpression &)expr, expression);
break;
default:
throw InternalException("Unrecognized expression type in logical operator visitor");
}
if (result) {
*expression = move(result);
} else {
// visit the children of this node
VisitExpressionChildren(expr);
}
}
void LogicalOperatorVisitor::VisitExpressionChildren(Expression &expr) {
ExpressionIterator::EnumerateChildren(expr, [&](unique_ptr<Expression> &expr) { VisitExpression(&expr); });
}
// these are all default methods that can be overriden
// we don't care about coverage here
// LCOV_EXCL_START
unique_ptr<Expression> LogicalOperatorVisitor::VisitReplace(BoundAggregateExpression &expr,
unique_ptr<Expression> *expr_ptr) {
return nullptr;
}
unique_ptr<Expression> LogicalOperatorVisitor::VisitReplace(BoundBetweenExpression &expr,
unique_ptr<Expression> *expr_ptr) {
return nullptr;
}
unique_ptr<Expression> LogicalOperatorVisitor::VisitReplace(BoundCaseExpression &expr,
unique_ptr<Expression> *expr_ptr) {
return nullptr;
}
unique_ptr<Expression> LogicalOperatorVisitor::VisitReplace(BoundCastExpression &expr,
unique_ptr<Expression> *expr_ptr) {
return nullptr;
}
unique_ptr<Expression> LogicalOperatorVisitor::VisitReplace(BoundColumnRefExpression &expr,
unique_ptr<Expression> *expr_ptr) {
return nullptr;
}
unique_ptr<Expression> LogicalOperatorVisitor::VisitReplace(BoundComparisonExpression &expr,
unique_ptr<Expression> *expr_ptr) {
return nullptr;
}
unique_ptr<Expression> LogicalOperatorVisitor::VisitReplace(BoundConjunctionExpression &expr,
unique_ptr<Expression> *expr_ptr) {
return nullptr;
}
unique_ptr<Expression> LogicalOperatorVisitor::VisitReplace(BoundConstantExpression &expr,
unique_ptr<Expression> *expr_ptr) {
return nullptr;
}
unique_ptr<Expression> LogicalOperatorVisitor::VisitReplace(BoundDefaultExpression &expr,
unique_ptr<Expression> *expr_ptr) {
return nullptr;
}
unique_ptr<Expression> LogicalOperatorVisitor::VisitReplace(BoundFunctionExpression &expr,
unique_ptr<Expression> *expr_ptr) {
return nullptr;
}
unique_ptr<Expression> LogicalOperatorVisitor::VisitReplace(BoundOperatorExpression &expr,
unique_ptr<Expression> *expr_ptr) {
return nullptr;
}
unique_ptr<Expression> LogicalOperatorVisitor::VisitReplace(BoundParameterExpression &expr,
unique_ptr<Expression> *expr_ptr) {
return nullptr;
}
unique_ptr<Expression> LogicalOperatorVisitor::VisitReplace(BoundReferenceExpression &expr,
unique_ptr<Expression> *expr_ptr) {
return nullptr;
}
unique_ptr<Expression> LogicalOperatorVisitor::VisitReplace(BoundSubqueryExpression &expr,
unique_ptr<Expression> *expr_ptr) {
return nullptr;
}
unique_ptr<Expression> LogicalOperatorVisitor::VisitReplace(BoundWindowExpression &expr,
unique_ptr<Expression> *expr_ptr) {
return nullptr;
}
unique_ptr<Expression> LogicalOperatorVisitor::VisitReplace(BoundUnnestExpression &expr,
unique_ptr<Expression> *expr_ptr) {
return nullptr;
}
// LCOV_EXCL_STOP
} // namespace duckdb