| 1 | #include "duckdb/execution/aggregate_hashtable.hpp" |
| 2 | #include "duckdb/execution/operator/join/physical_delim_join.hpp" |
| 3 | #include "duckdb/execution/operator/join/physical_hash_join.hpp" |
| 4 | #include "duckdb/execution/operator/projection/physical_projection.hpp" |
| 5 | #include "duckdb/execution/physical_plan_generator.hpp" |
| 6 | #include "duckdb/planner/operator/logical_delim_join.hpp" |
| 7 | #include "duckdb/planner/expression/bound_aggregate_expression.hpp" |
| 8 | #include "duckdb/planner/expression/bound_reference_expression.hpp" |
| 9 | #include "duckdb/execution/operator/aggregate/physical_hash_aggregate.hpp" |
| 10 | |
| 11 | namespace duckdb { |
| 12 | |
| 13 | static void GatherDelimScans(const PhysicalOperator &op, vector<const_reference<PhysicalOperator>> &delim_scans) { |
| 14 | if (op.type == PhysicalOperatorType::DELIM_SCAN) { |
| 15 | delim_scans.push_back(x: op); |
| 16 | } |
| 17 | for (auto &child : op.children) { |
| 18 | GatherDelimScans(op: *child, delim_scans); |
| 19 | } |
| 20 | } |
| 21 | |
| 22 | unique_ptr<PhysicalOperator> PhysicalPlanGenerator::CreatePlan(LogicalDelimJoin &op) { |
| 23 | // first create the underlying join |
| 24 | auto plan = CreatePlan(op&: op.Cast<LogicalComparisonJoin>()); |
| 25 | // this should create a join, not a cross product |
| 26 | D_ASSERT(plan && plan->type != PhysicalOperatorType::CROSS_PRODUCT); |
| 27 | // duplicate eliminated join |
| 28 | // first gather the scans on the duplicate eliminated data set from the RHS |
| 29 | vector<const_reference<PhysicalOperator>> delim_scans; |
| 30 | GatherDelimScans(op: *plan->children[1], delim_scans); |
| 31 | if (delim_scans.empty()) { |
| 32 | // no duplicate eliminated scans in the RHS! |
| 33 | // in this case we don't need to create a delim join |
| 34 | // just push the normal join |
| 35 | return plan; |
| 36 | } |
| 37 | vector<LogicalType> delim_types; |
| 38 | vector<unique_ptr<Expression>> distinct_groups, distinct_expressions; |
| 39 | for (auto &delim_expr : op.duplicate_eliminated_columns) { |
| 40 | D_ASSERT(delim_expr->type == ExpressionType::BOUND_REF); |
| 41 | auto &bound_ref = delim_expr->Cast<BoundReferenceExpression>(); |
| 42 | delim_types.push_back(x: bound_ref.return_type); |
| 43 | distinct_groups.push_back(x: make_uniq<BoundReferenceExpression>(args&: bound_ref.return_type, args&: bound_ref.index)); |
| 44 | } |
| 45 | // now create the duplicate eliminated join |
| 46 | auto delim_join = make_uniq<PhysicalDelimJoin>(args&: op.types, args: std::move(plan), args&: delim_scans, args&: op.estimated_cardinality); |
| 47 | // we still have to create the DISTINCT clause that is used to generate the duplicate eliminated chunk |
| 48 | delim_join->distinct = make_uniq<PhysicalHashAggregate>(args&: context, args&: delim_types, args: std::move(distinct_expressions), |
| 49 | args: std::move(distinct_groups), args&: op.estimated_cardinality); |
| 50 | return std::move(delim_join); |
| 51 | } |
| 52 | |
| 53 | } // namespace duckdb |
| 54 | |