MCPcopy Create free account
hub / github.com/NodeDB-Lab/nodedb / convert_join

Function convert_join

nodedb/src/control/planner/sql_plan_convert/scan/join.rs:76–162  ·  view source on GitHub ↗
(
    p: JoinPlanParams<'_>,
)

Source from the content-addressed store, hash-verified

74}
75
76pub(in crate::control::planner::sql_plan_convert) fn convert_join(
77 p: JoinPlanParams<'_>,
78) -> crate::Result<Vec<PhysicalTask>> {
79 let JoinPlanParams {
80 left,
81 right,
82 on,
83 join_type,
84 condition,
85 limit,
86 projection,
87 filters,
88 tenant_id,
89 ctx,
90 } = p;
91 let mut left_collection =
92 super::super::convert::db_qualified(p.ctx.database_id, &extract_collection_name(left));
93 let mut right_collection =
94 super::super::convert::db_qualified(p.ctx.database_id, &extract_collection_name(right));
95 let mut left_alias = extract_scan_alias(left);
96 let mut right_alias = extract_scan_alias(right);
97 let join_projection = extract_join_projection_specs(projection);
98 let filter_bytes = serialize_join_filters(filters, condition)?;
99
100 // Check if the left side is a nested join (multi-way join).
101 // If so, convert the inner join to a physical plan and pass it
102 // as `inline_left` so the executor runs it first.
103 let inline_left = if matches!(left, SqlPlan::Join { .. }) {
104 let inner_tasks = convert_one(left, tenant_id, ctx)?;
105 inner_tasks.into_iter().next().map(|t| Box::new(t.plan))
106 } else {
107 None
108 };
109 let inline_right = super::super::aggregate::inline_join_side(right, tenant_id, ctx)?;
110
111 // RIGHT JOIN → swap sides and convert to LEFT JOIN.
112 let mut on_keys = on.to_vec();
113 let mut inline_left = inline_left;
114 let mut inline_right = inline_right;
115 let effective_join_type = if join_type.as_str() == "right" {
116 std::mem::swap(&mut left_collection, &mut right_collection);
117 std::mem::swap(&mut left_alias, &mut right_alias);
118 std::mem::swap(&mut inline_left, &mut inline_right);
119 on_keys = on_keys.into_iter().map(|(l, r)| (r, l)).collect();
120 "left".to_string()
121 } else {
122 join_type.as_str().to_string()
123 };
124
125 // Analyze join children for selective-predicate bitmap pushdown.
126 // The analysis runs on the *original* (pre-swap) children since it inspects
127 // SqlPlan shape. After the RIGHT→LEFT swap, we swap the resulting hints too.
128 let bitmap_hints = nodedb_sql::planner::bitmap_emit::hashjoin::analyze_join_sides(left, right);
129 let (mut raw_left_bm, mut raw_right_bm) = (bitmap_hints.left, bitmap_hints.right);
130 if join_type.as_str() == "right" {
131 std::mem::swap(&mut raw_left_bm, &mut raw_right_bm);
132 }
133 let db_id = p.ctx.database_id;

Callers

nothing calls this directly

Calls 14

db_qualifiedFunction · 0.85
extract_scan_aliasFunction · 0.85
serialize_join_filtersFunction · 0.85
convert_oneFunction · 0.85
inline_join_sideFunction · 0.85
analyze_join_sidesFunction · 0.85
bitmap_hint_to_planFunction · 0.85
collectMethod · 0.80
to_stringMethod · 0.80
extract_collection_nameFunction · 0.50
nextMethod · 0.45

Tested by

no test coverage detected