rust_ef/query/
execute_update.rs1use std::marker::PhantomData;
7use std::sync::Arc;
8
9use crate::entity::IEntityType;
10use crate::error::EFResult;
11use crate::provider::{DbValue, IDatabaseProvider};
12
13use super::compile::{compile_bool_expr, PortablePlaceholderGenerator};
14use super::state::QueryState;
15
16#[derive(Clone)]
18pub struct ExecuteUpdateBuilder<T: IEntityType> {
19 pub(crate) state: QueryState,
20 pub(crate) updates: Vec<(String, DbValue)>,
21 pub(crate) provider: Option<Arc<dyn IDatabaseProvider>>,
22 pub(crate) _phantom: PhantomData<T>,
23}
24
25impl<T: IEntityType> ExecuteUpdateBuilder<T> {
26 #[doc(hidden)]
31 pub fn set_column_internal(mut self, column: &'static str, value: impl Into<DbValue>) -> Self {
32 self.updates.push((column.to_string(), value.into()));
33 self
34 }
35
36 pub fn to_sql(&self) -> String {
38 let gen: &dyn crate::provider::ISqlGenerator = self
39 .provider
40 .as_ref()
41 .map(|p| p.sql_generator())
42 .unwrap_or(&PortablePlaceholderGenerator);
43 let mut param_idx = 1usize;
44 let sets: Vec<String> = self
45 .updates
46 .iter()
47 .map(|(col, _)| {
48 let ph = gen.parameter_placeholder(param_idx);
49 param_idx += 1;
50 format!("{} = {}", col, ph)
51 })
52 .collect();
53 let where_clause = match &self.state.where_expr {
54 Some(expr) => {
55 let mut where_idx = param_idx;
56 compile_bool_expr(expr, gen, &mut where_idx)
57 }
58 None => String::new(),
59 };
60 if where_clause.is_empty() {
61 format!("UPDATE {} SET {}", self.state.from, sets.join(", "))
62 } else {
63 format!(
64 "UPDATE {} SET {} WHERE {}",
65 self.state.from,
66 sets.join(", "),
67 where_clause
68 )
69 }
70 }
71
72 pub fn params(&self) -> Vec<DbValue> {
74 let mut params: Vec<DbValue> = self.updates.iter().map(|(_, v)| v.clone()).collect();
75 params.extend_from_slice(&self.state.parameters);
76 params
77 }
78
79 pub async fn execute(self) -> EFResult<u64> {
85 if self.updates.is_empty() {
86 return Err(crate::error::EFError::configuration(
87 "execute_update requires at least one set column (e.g. \
88 `set_column_internal`)"
89 .to_string(),
90 ));
91 }
92 let sql = self.to_sql();
93 let params = self.params();
94 let provider = self.provider.as_ref().ok_or_else(|| {
95 crate::error::EFError::configuration(
96 "No provider attached to ExecuteUpdateBuilder.".to_string(),
97 )
98 })?;
99 let mut conn = provider.get_connection().await?;
100 conn.execute(&sql, ¶ms).await
101 }
102}