(
&self,
left: LogicalPlan,
right: LogicalPlan,
constraint: JoinConstraint,
join_type: JoinType,
planner_context: &mut PlannerContext,
)
| 111 | } |
| 112 | |
| 113 | fn parse_join( |
| 114 | &self, |
| 115 | left: LogicalPlan, |
| 116 | right: LogicalPlan, |
| 117 | constraint: JoinConstraint, |
| 118 | join_type: JoinType, |
| 119 | planner_context: &mut PlannerContext, |
| 120 | ) -> Result<LogicalPlan> { |
| 121 | match constraint { |
| 122 | JoinConstraint::On(sql_expr) => { |
| 123 | let join_schema = left.schema().join(right.schema())?; |
| 124 | // parse ON expression |
| 125 | let expr = self.sql_to_expr(sql_expr, &join_schema, planner_context)?; |
| 126 | LogicalPlanBuilder::from(left) |
| 127 | .join_on(right, join_type, Some(expr))? |
| 128 | .build() |
| 129 | } |
| 130 | JoinConstraint::Using(object_names) => { |
| 131 | let keys = object_names |
| 132 | .into_iter() |
| 133 | .map(|object_name| { |
| 134 | let ObjectName(mut object_names) = object_name; |
| 135 | if object_names.len() != 1 { |
| 136 | not_impl_err!( |
| 137 | "Invalid identifier in USING clause. Expected single identifier, got {}", ObjectName(object_names) |
| 138 | ) |
| 139 | } else { |
| 140 | let id = object_names.swap_remove(0); |
| 141 | id.as_ident() |
| 142 | .ok_or_else(|| { |
| 143 | plan_datafusion_err!( |
| 144 | "Expected identifier in USING clause" |
| 145 | ) |
| 146 | }) |
| 147 | .map(|ident| Column::from_name(self.ident_normalizer.normalize(ident.clone()))) |
| 148 | } |
| 149 | }) |
| 150 | .collect::<Result<Vec<_>>>()?; |
| 151 | |
| 152 | LogicalPlanBuilder::from(left) |
| 153 | .join_using(right, join_type, keys)? |
| 154 | .build() |
| 155 | } |
| 156 | JoinConstraint::Natural => { |
| 157 | let left_cols: HashSet<&String> = |
| 158 | left.schema().fields().iter().map(|f| f.name()).collect(); |
| 159 | let keys: Vec<Column> = right |
| 160 | .schema() |
| 161 | .fields() |
| 162 | .iter() |
| 163 | .map(|f| f.name()) |
| 164 | .filter(|f| left_cols.contains(f)) |
| 165 | .map(Column::from_name) |
| 166 | .collect(); |
| 167 | if keys.is_empty() { |
| 168 | self.parse_cross_join(left, right) |
| 169 | } else { |
| 170 | LogicalPlanBuilder::from(left) |
no test coverage detected