1#include "duckdb/execution/operator/join/physical_hash_join.hpp"
2#include "duckdb/execution/operator/set/physical_union.hpp"
3#include "duckdb/execution/physical_plan_generator.hpp"
4#include "duckdb/planner/expression/bound_reference_expression.hpp"
5#include "duckdb/planner/operator/logical_set_operation.hpp"
6
7using namespace duckdb;
8using namespace std;
9
10unique_ptr<PhysicalOperator> PhysicalPlanGenerator::CreatePlan(LogicalSetOperation &op) {
11 assert(op.children.size() == 2);
12
13 auto left = CreatePlan(*op.children[0]);
14 auto right = CreatePlan(*op.children[1]);
15
16 if (left->GetTypes() != right->GetTypes()) {
17 throw Exception("Type mismatch for SET OPERATION");
18 }
19
20 switch (op.type) {
21 case LogicalOperatorType::UNION:
22 // UNION
23 return make_unique<PhysicalUnion>(op, move(left), move(right));
24 default: {
25 // EXCEPT/INTERSECT
26 assert(op.type == LogicalOperatorType::EXCEPT || op.type == LogicalOperatorType::INTERSECT);
27 auto &types = left->GetTypes();
28 vector<JoinCondition> conditions;
29 // create equality condition for all columns
30 for (idx_t i = 0; i < types.size(); i++) {
31 JoinCondition cond;
32 cond.comparison = ExpressionType::COMPARE_EQUAL;
33 cond.left = make_unique<BoundReferenceExpression>(types[i], i);
34 cond.right = make_unique<BoundReferenceExpression>(types[i], i);
35 cond.null_values_are_equal = true;
36 conditions.push_back(move(cond));
37 }
38 // EXCEPT is ANTI join
39 // INTERSECT is SEMI join
40 JoinType join_type = op.type == LogicalOperatorType::EXCEPT ? JoinType::ANTI : JoinType::SEMI;
41 return make_unique<PhysicalHashJoin>(context, op, move(left), move(right), move(conditions), join_type);
42 }
43 }
44}
45