Plan a `MERGE INTO target USING source ON ... WHEN ... THEN ...` statement.
(stmt: &ast::Statement, catalog: &dyn SqlCatalog)
| 20 | |
| 21 | /// Plan a `MERGE INTO target USING source ON ... WHEN ... THEN ...` statement. |
| 22 | pub fn plan_merge(stmt: &ast::Statement, catalog: &dyn SqlCatalog) -> Result<Vec<SqlPlan>> { |
| 23 | let ast::Statement::Merge(merge) = stmt else { |
| 24 | return Err(SqlError::Parse { |
| 25 | detail: "expected MERGE statement".into(), |
| 26 | }); |
| 27 | }; |
| 28 | |
| 29 | if merge.clauses.is_empty() { |
| 30 | return Err(SqlError::Parse { |
| 31 | detail: "MERGE statement requires at least one WHEN arm".into(), |
| 32 | }); |
| 33 | } |
| 34 | |
| 35 | // ── Resolve target ── |
| 36 | let (target_name, target_alias) = extract_table_factor_name_alias(&merge.table)?; |
| 37 | // The ON clause uses the alias (or table name if no alias) as the qualifier. |
| 38 | let target_ref = target_alias.as_deref().unwrap_or(target_name.as_str()); |
| 39 | let target_info = catalog |
| 40 | .get_collection(DatabaseId::DEFAULT, &target_name)? |
| 41 | .ok_or_else(|| SqlError::UnknownTable { |
| 42 | name: target_name.clone(), |
| 43 | })?; |
| 44 | |
| 45 | // ── Resolve source ── |
| 46 | let source_plan = plan_merge_source(&merge.source, catalog)?; |
| 47 | let source_alias = merge_source_alias(&merge.source, &source_plan); |
| 48 | |
| 49 | // ── Parse ON clause into equi-join columns ── |
| 50 | let (target_join_col, source_join_col) = |
| 51 | extract_merge_equijoin(&merge.on, target_ref, &source_alias)?; |
| 52 | |
| 53 | // ── Convert WHEN clauses ── |
| 54 | let clauses = convert_merge_clauses(&merge.clauses, target_ref, &source_alias)?; |
| 55 | |
| 56 | // ── Dispatch to engine rules ── |
| 57 | let rules = engine_rules::resolve_engine_rules(target_info.engine); |
| 58 | rules.plan_merge(MergeParams { |
| 59 | collection: target_name, |
| 60 | source: Box::new(source_plan), |
| 61 | target_join_col, |
| 62 | source_join_col, |
| 63 | source_alias, |
| 64 | clauses, |
| 65 | returning: false, |
| 66 | }) |
| 67 | } |
| 68 | |
| 69 | // ── Source planning ──────────────────────────────────────────────────────── |
| 70 |
no test coverage detected