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::{
14 build_where_clause_with_offset, compile_bool_expr, PortablePlaceholderGenerator,
15};
16use super::state::QueryState;
17
18#[derive(Clone)]
20pub struct ExecuteUpdateBuilder<T: IEntityType> {
21 pub(crate) state: QueryState,
22 pub(crate) updates: Vec<(String, DbValue)>,
23 pub(crate) provider: Option<Arc<dyn IDatabaseProvider>>,
24 pub(crate) _phantom: PhantomData<T>,
25}
26
27impl<T: IEntityType> ExecuteUpdateBuilder<T> {
28 #[doc(hidden)]
33 pub fn set_column_internal(mut self, column: &'static str, value: impl Into<DbValue>) -> Self {
34 self.updates.push((column.to_string(), value.into()));
35 self
36 }
37
38 pub fn to_sql(&self) -> String {
40 let gen: &dyn crate::provider::ISqlGenerator = self
41 .provider
42 .as_ref()
43 .map(|p| p.sql_generator())
44 .unwrap_or(&PortablePlaceholderGenerator);
45 let mut param_idx = 1usize;
46 let sets: Vec<String> = self
47 .updates
48 .iter()
49 .map(|(col, _)| {
50 let ph = gen.parameter_placeholder(param_idx);
51 param_idx += 1;
52 format!("{} = {}", col, ph)
53 })
54 .collect();
55 let where_clause = if let Some(ref expr) = self.state.where_expr {
56 let mut param_idx = param_idx;
57 compile_bool_expr(expr, gen, &mut param_idx)
58 } else {
59 build_where_clause_with_offset(&self.state.filters, gen, param_idx)
60 };
61 if where_clause.is_empty() {
62 format!("UPDATE {} SET {}", self.state.from, sets.join(", "))
63 } else {
64 format!(
65 "UPDATE {} SET {} WHERE {}",
66 self.state.from,
67 sets.join(", "),
68 where_clause
69 )
70 }
71 }
72
73 pub fn params(&self) -> Vec<DbValue> {
75 let mut params: Vec<DbValue> = self.updates.iter().map(|(_, v)| v.clone()).collect();
76 params.extend_from_slice(&self.state.parameters);
77 params
78 }
79
80 pub async fn execute(self) -> EFResult<u64> {
82 let sql = self.to_sql();
83 let params = self.params();
84 let provider = self.provider.as_ref().ok_or_else(|| {
85 crate::error::EFError::configuration(
86 "No provider attached to ExecuteUpdateBuilder.".to_string(),
87 )
88 })?;
89 let mut conn = provider.get_connection().await?;
90 conn.execute(&sql, ¶ms).await
91 }
92}