1#include "duckdb/optimizer/filter_pushdown.hpp"
2#include "duckdb/planner/operator/logical_comparison_join.hpp"
3#include "duckdb/planner/operator/logical_cross_product.hpp"
4
5using namespace duckdb;
6using namespace std;
7
8using Filter = FilterPushdown::Filter;
9
10unique_ptr<LogicalOperator> FilterPushdown::PushdownCrossProduct(unique_ptr<LogicalOperator> op) {
11 assert(op->type == LogicalOperatorType::CROSS_PRODUCT);
12 FilterPushdown left_pushdown(optimizer), right_pushdown(optimizer);
13 vector<unique_ptr<Expression>> join_conditions;
14 unordered_set<idx_t> left_bindings, right_bindings;
15 if (filters.size() > 0) {
16 // check to see into which side we should push the filters
17 // first get the LHS and RHS bindings
18 LogicalJoin::GetTableReferences(*op->children[0], left_bindings);
19 LogicalJoin::GetTableReferences(*op->children[1], right_bindings);
20 // now check the set of filters
21 for (auto &f : filters) {
22 auto side = JoinSide::GetJoinSide(f->bindings, left_bindings, right_bindings);
23 if (side == JoinSide::LEFT) {
24 // bindings match left side: push into left
25 left_pushdown.filters.push_back(move(f));
26 } else if (side == JoinSide::RIGHT) {
27 // bindings match right side: push into right
28 right_pushdown.filters.push_back(move(f));
29 } else {
30 assert(side == JoinSide::BOTH);
31 // bindings match both: turn into join condition
32 join_conditions.push_back(move(f->filter));
33 }
34 }
35 }
36 op->children[0] = left_pushdown.Rewrite(move(op->children[0]));
37 op->children[1] = right_pushdown.Rewrite(move(op->children[1]));
38
39 if (join_conditions.size() > 0) {
40 // join conditions found: turn into inner join
41 return LogicalComparisonJoin::CreateJoin(JoinType::INNER, move(op->children[0]), move(op->children[1]),
42 left_bindings, right_bindings, join_conditions);
43 } else {
44 // no join conditions found: keep as cross product
45 return op;
46 }
47}
48