| 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 | |
| 5 | using namespace duckdb; |
| 6 | using namespace std; |
| 7 | |
| 8 | using Filter = FilterPushdown::Filter; |
| 9 | |
| 10 | unique_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 | |