1#include "duckdb/optimizer/filter_pullup.hpp"
2#include "duckdb/planner/operator/logical_set_operation.hpp"
3#include "duckdb/planner/expression/bound_columnref_expression.hpp"
4#include "duckdb/planner/expression_iterator.hpp"
5
6namespace duckdb {
7
8static void ReplaceFilterTableIndex(Expression &expr, LogicalSetOperation &setop) {
9 if (expr.type == ExpressionType::BOUND_COLUMN_REF) {
10 auto &colref = expr.Cast<BoundColumnRefExpression>();
11 D_ASSERT(colref.depth == 0);
12
13 colref.binding.table_index = setop.table_index;
14 return;
15 }
16 ExpressionIterator::EnumerateChildren(expression&: expr, callback: [&](Expression &child) { ReplaceFilterTableIndex(expr&: child, setop); });
17}
18
19unique_ptr<LogicalOperator> FilterPullup::PullupSetOperation(unique_ptr<LogicalOperator> op) {
20 D_ASSERT(op->type == LogicalOperatorType::LOGICAL_INTERSECT || op->type == LogicalOperatorType::LOGICAL_EXCEPT);
21 can_add_column = false;
22 can_pullup = true;
23 if (op->type == LogicalOperatorType::LOGICAL_INTERSECT) {
24 op = PullupBothSide(op: std::move(op));
25 } else {
26 // EXCEPT only pull ups from LHS
27 op = PullupFromLeft(op: std::move(op));
28 }
29 if (op->type == LogicalOperatorType::LOGICAL_FILTER) {
30 auto &filter = op->Cast<LogicalFilter>();
31 auto &setop = filter.children[0]->Cast<LogicalSetOperation>();
32 for (idx_t i = 0; i < filter.expressions.size(); ++i) {
33 ReplaceFilterTableIndex(expr&: *filter.expressions[i], setop);
34 }
35 }
36 return op;
37}
38
39} // namespace duckdb
40