Single attempt of UPDATE execution.
(
ctx: &SQLContext,
update: &Update,
table: &Table,
)
| 86 | |
| 87 | /// Single attempt of UPDATE execution. |
| 88 | async fn execute_update_once( |
| 89 | ctx: &SQLContext, |
| 90 | update: &Update, |
| 91 | table: &Table, |
| 92 | ) -> DFResult<DataFrame> { |
| 93 | // 1. Extract SET assignments |
| 94 | let mut columns = Vec::new(); |
| 95 | let mut exprs = Vec::new(); |
| 96 | for assignment in &update.assignments { |
| 97 | let col_name = match &assignment.target { |
| 98 | AssignmentTarget::ColumnName(name) => name |
| 99 | .0 |
| 100 | .last() |
| 101 | .and_then(|p| p.as_ident()) |
| 102 | .map(|id| id.value.clone()) |
| 103 | .ok_or_else(|| { |
| 104 | DataFusionError::Plan(format!("Invalid column name in SET: {name}")) |
| 105 | })?, |
| 106 | AssignmentTarget::Tuple(_) => { |
| 107 | return Err(DataFusionError::Plan( |
| 108 | "Tuple assignment in UPDATE SET is not supported".to_string(), |
| 109 | )); |
| 110 | } |
| 111 | }; |
| 112 | columns.push(col_name); |
| 113 | exprs.push(assignment.value.to_string()); |
| 114 | } |
| 115 | |
| 116 | // 2. Create DataEvolutionWriter (validates preconditions) |
| 117 | let mut writer = |
| 118 | DataEvolutionWriter::new(table, columns.clone()).map_err(to_datafusion_error)?; |
| 119 | |
| 120 | // 3. Query the target table directly with WHERE filter. |
| 121 | let table_ref = update.table.to_string(); |
| 122 | |
| 123 | let select_parts: Vec<String> = |
| 124 | std::iter::once("\"_ROW_ID\"".to_string()) |
| 125 | .chain(columns.iter().zip(exprs.iter()).map(|(col, expr)| { |
| 126 | format!("{expr} AS {}", quote_identifier(&format!("__upd_{col}"))) |
| 127 | })) |
| 128 | .collect(); |
| 129 | |
| 130 | let select_clause = select_parts.join(", "); |
| 131 | let where_clause = match &update.selection { |
| 132 | Some(expr) => format!(" WHERE {expr}"), |
| 133 | None => String::new(), |
| 134 | }; |
| 135 | |
| 136 | let query_sql = format!("SELECT {select_clause} FROM {table_ref}{where_clause}"); |
| 137 | let batches = ctx.ctx().sql(&query_sql).await?.collect().await?; |
| 138 | |
| 139 | // 4. Project update columns (rename __upd_X → X) |
| 140 | let total_count: u64 = batches.iter().map(|b| b.num_rows() as u64).sum(); |
| 141 | if total_count == 0 { |
| 142 | return ok_result(ctx.ctx(), 0); |
| 143 | } |
| 144 | |
| 145 | let update_batches = project_update_columns(&batches, &columns)?; |
no test coverage detected