Try to extract `(target_col, source_col)` from an equality expression where one side is `target_ref.col` and the other is `source_ref.col`. Also handles unqualified names by assuming they belong to the target.
(
expr: &ast::Expr,
target_ref: &str,
source_ref: &str,
)
| 223 | /// where one side is `target_ref.col` and the other is `source_ref.col`. |
| 224 | /// Also handles unqualified names by assuming they belong to the target. |
| 225 | fn try_equijoin_pair( |
| 226 | expr: &ast::Expr, |
| 227 | target_ref: &str, |
| 228 | source_ref: &str, |
| 229 | ) -> Option<(String, String)> { |
| 230 | let ast::Expr::BinaryOp { |
| 231 | left, |
| 232 | op: ast::BinaryOperator::Eq, |
| 233 | right, |
| 234 | } = expr |
| 235 | else { |
| 236 | return None; |
| 237 | }; |
| 238 | |
| 239 | let lhs = qualified_ident_pair(left); |
| 240 | let rhs = qualified_ident_pair(right); |
| 241 | |
| 242 | match (lhs, rhs) { |
| 243 | (Some((lt, lc)), Some((rt, rc))) => { |
| 244 | if lt == target_ref && rt == source_ref { |
| 245 | Some((lc, rc)) |
| 246 | } else if lt == source_ref && rt == target_ref { |
| 247 | Some((rc, lc)) |
| 248 | } else { |
| 249 | None |
| 250 | } |
| 251 | } |
| 252 | // One side is unqualified — treat it as belonging to target. |
| 253 | (Some((t, c)), None) if t == source_ref => { |
| 254 | if let ast::Expr::Identifier(ident) = right.as_ref() { |
| 255 | Some((normalize_ident(ident), c)) |
| 256 | } else { |
| 257 | None |
| 258 | } |
| 259 | } |
| 260 | (None, Some((t, c))) if t == source_ref => { |
| 261 | if let ast::Expr::Identifier(ident) = left.as_ref() { |
| 262 | Some((normalize_ident(ident), c)) |
| 263 | } else { |
| 264 | None |
| 265 | } |
| 266 | } |
| 267 | _ => None, |
| 268 | } |
| 269 | } |
| 270 | |
| 271 | /// Convert `update.assignments` into `Vec<(col, SqlExpr)>`. |
| 272 | fn convert_assignments(assignments: &[ast::Assignment]) -> Result<Vec<(String, SqlExpr)>> { |
no test coverage detected