Apply a join with using constraint, which duplicates all join columns in output schema.
(
self,
right: LogicalPlan,
join_type: JoinType,
using_keys: Vec<Column>,
)
| 1168 | |
| 1169 | /// Apply a join with using constraint, which duplicates all join columns in output schema. |
| 1170 | pub fn join_using( |
| 1171 | self, |
| 1172 | right: LogicalPlan, |
| 1173 | join_type: JoinType, |
| 1174 | using_keys: Vec<Column>, |
| 1175 | ) -> Result<Self> { |
| 1176 | let left_keys: Vec<Column> = using_keys |
| 1177 | .clone() |
| 1178 | .into_iter() |
| 1179 | .map(|c| Self::normalize(&self.plan, c)) |
| 1180 | .collect::<Result<_>>()?; |
| 1181 | let right_keys: Vec<Column> = using_keys |
| 1182 | .into_iter() |
| 1183 | .map(|c| Self::normalize(&right, c)) |
| 1184 | .collect::<Result<_>>()?; |
| 1185 | |
| 1186 | let on: Vec<(_, _)> = left_keys.into_iter().zip(right_keys).collect(); |
| 1187 | let mut join_on: Vec<(Expr, Expr)> = vec![]; |
| 1188 | let mut filters: Option<Expr> = None; |
| 1189 | for (l, r) in &on { |
| 1190 | if self.plan.schema().has_column(l) |
| 1191 | && right.schema().has_column(r) |
| 1192 | && can_hash( |
| 1193 | datafusion_common::ExprSchema::field_from_column( |
| 1194 | self.plan.schema(), |
| 1195 | l, |
| 1196 | )? |
| 1197 | .data_type(), |
| 1198 | ) |
| 1199 | { |
| 1200 | join_on.push((Expr::Column(l.clone()), Expr::Column(r.clone()))); |
| 1201 | } else if self.plan.schema().has_column(l) |
| 1202 | && right.schema().has_column(r) |
| 1203 | && can_hash( |
| 1204 | datafusion_common::ExprSchema::field_from_column( |
| 1205 | self.plan.schema(), |
| 1206 | r, |
| 1207 | )? |
| 1208 | .data_type(), |
| 1209 | ) |
| 1210 | { |
| 1211 | join_on.push((Expr::Column(r.clone()), Expr::Column(l.clone()))); |
| 1212 | } else { |
| 1213 | let expr = binary_expr( |
| 1214 | Expr::Column(l.clone()), |
| 1215 | Operator::Eq, |
| 1216 | Expr::Column(r.clone()), |
| 1217 | ); |
| 1218 | match filters { |
| 1219 | None => filters = Some(expr), |
| 1220 | Some(filter_expr) => filters = Some(and(expr, filter_expr)), |
| 1221 | } |
| 1222 | } |
| 1223 | } |
| 1224 | |
| 1225 | if join_on.is_empty() { |
| 1226 | let join = Self::from(self.plan).cross_join(right)?; |
| 1227 | join.filter(filters.ok_or_else(|| { |