diff --git a/core/translate/optimizer/mod.rs b/core/translate/optimizer/mod.rs index 2d02121b9..21dadf535 100644 --- a/core/translate/optimizer/mod.rs +++ b/core/translate/optimizer/mod.rs @@ -47,10 +47,10 @@ pub fn optimize_plan(plan: &mut Plan, schema: &Schema) -> Result<()> { } } } - // Context for everything is created inside the plan + // Context for everything is created with values inside the plan tracing::debug!( target = "optimized_plan", - plan = plan.to_sql_string(&crate::translate::plan::PlanContext(&[])) + plan_sql = plan.to_sql_string(&crate::translate::plan::PlanContext(&[])) ); Ok(()) } diff --git a/core/translate/plan.rs b/core/translate/plan.rs index ffee2449a..2d7deaed5 100644 --- a/core/translate/plan.rs +++ b/core/translate/plan.rs @@ -1423,7 +1423,9 @@ impl ToSqlString for Plan { fn to_sql_string(&self, context: &C) -> String { // Make the Plans pass their own context match self { - Self::Select(select) => select.to_sql_string(context), + Self::Select(select) => select.to_sql_string(&PlanContext( + &select.table_references.iter().collect::>(), + )), Self::CompoundSelect { first, rest, @@ -1472,7 +1474,7 @@ impl ToSqlString for Plan { ret.join(" ") } Self::Delete(delete) => delete.to_sql_string(context), - _ => todo!(), + Self::Update(update) => update.to_sql_string(context), } } } @@ -1517,11 +1519,8 @@ impl ToSqlString for TableReference { impl ToSqlString for SelectPlan { fn to_sql_string( &self, - _context: &C, + context: &C, ) -> String { - let context = self.table_references.iter().collect::>(); - let context = &PlanContext(&context); - let mut ret = Vec::new(); // VALUES SELECT statement if !self.values.is_empty() { @@ -1679,3 +1678,73 @@ impl ToSqlString for DeletePlan { ret.join(" ") } } + +impl ToSqlString for UpdatePlan { + fn to_sql_string(&self, _context: &C) -> String { + let table_ref = self + .table_references + .first() + .expect("UPDATE Plan should have only one table reference"); + let context = &self.table_references.iter().collect::>(); + let context = &PlanContext(context); + let mut ret = Vec::new(); + + // TODO: we don't work with conflict clauses yet + + ret.push(format!("UPDATE {} SET", table_ref.table.get_name())); + + // TODO: does not support column_name_list yet + ret.push( + self.set_clauses + .iter() + .map(|(col_idx, set_expr)| { + format!( + "{} = {}", + table_ref + .table + .get_column_at(*col_idx) + .as_ref() + .unwrap() + .name + .as_ref() + .unwrap(), + set_expr.to_sql_string(context) + ) + }) + .collect::>() + .join(", "), + ); + + if !self.where_clause.is_empty() { + ret.push("WHERE".to_string()); + ret.push( + self.where_clause + .iter() + .map(|where_clause| where_clause.expr.to_sql_string(context)) + .collect::>() + .join(" AND "), + ); + } + if let Some(order_by) = &self.order_by { + ret.push(format!( + "ORDER BY {}", + order_by + .iter() + .map(|(expr, order)| format!( + "{} {}", + expr.to_sql_string(context), + order.to_sql_string(context) + )) + .collect::>() + .join(", ") + )); + } + if let Some(limit) = &self.limit { + ret.push(format!("LIMIT {}", limit)); + } + if let Some(offset) = &self.offset { + ret.push(format!("OFFSET {}", offset)); + } + ret.join(" ") + } +}