Extract a single equi-join predicate of the form `target_table.col = source_table.col` (or the reverse) from a WHERE expression, returning `(target_col, source_col, remaining_filters)`. Also accepts `col = other_table.col` where `col` without a table qualifier is assumed to belong to the target (PostgreSQL behavior).
(
expr: &ast::Expr,
target_ref: &str,
source_ref: &str,
)
| 181 | /// Also accepts `col = other_table.col` where `col` without a table qualifier is |
| 182 | /// assumed to belong to the target (PostgreSQL behavior). |
| 183 | fn extract_join_predicate( |
| 184 | expr: &ast::Expr, |
| 185 | target_ref: &str, |
| 186 | source_ref: &str, |
| 187 | ) -> Result<(String, String, Vec<Filter>)> { |
| 188 | // Flatten the top-level AND chain. |
| 189 | let mut conjuncts: Vec<ast::Expr> = Vec::new(); |
| 190 | flatten_and_expr(expr, &mut conjuncts); |
| 191 | |
| 192 | // Find the first conjunct that is an equi-join between target and source. |
| 193 | let mut join_idx: Option<usize> = None; |
| 194 | let mut target_col = String::new(); |
| 195 | let mut source_col = String::new(); |
| 196 | |
| 197 | for (i, conjunct) in conjuncts.iter().enumerate() { |
| 198 | if let Some((tc, sc)) = try_equijoin_pair(conjunct, target_ref, source_ref) { |
| 199 | target_col = tc; |
| 200 | source_col = sc; |
| 201 | join_idx = Some(i); |
| 202 | break; |
| 203 | } |
| 204 | } |
| 205 | |
| 206 | let join_idx = join_idx.ok_or_else(|| SqlError::Parse { |
| 207 | detail: format!( |
| 208 | "UPDATE ... FROM requires a WHERE clause equi-join predicate of the form \ |
| 209 | `{target_ref}.col = {source_ref}.col`; none found" |
| 210 | ), |
| 211 | })?; |
| 212 | |
| 213 | conjuncts.remove(join_idx); |
| 214 | |
| 215 | // Remaining conjuncts become target_filters. Strip table qualifier so |
| 216 | // `uf_target.score` becomes `score` — documents store bare field names. |
| 217 | let target_filters = strip_and_convert_filters(conjuncts, target_ref)?; |
| 218 | |
| 219 | Ok((target_col, source_col, target_filters)) |
| 220 | } |
| 221 | |
| 222 | /// Try to extract `(target_col, source_col)` from an equality expression |
| 223 | /// where one side is `target_ref.col` and the other is `source_ref.col`. |
no test coverage detected