1use super::builder::QueryBuilder;
4use super::types::*;
5use serde_json::Value;
6
7#[derive(Debug)]
9pub struct UpsertBuilder<M = ()> {
10 pub(crate) query_builder: QueryBuilder<M>,
11 pub(crate) conflict_columns: Vec<String>,
12 pub(crate) update_clauses: Vec<SetClause>,
13}
14
15impl<M> UpsertBuilder<M> {
16 pub fn update_set<T: Into<Value>>(mut self, column: &str, value: T) -> Self {
18 self.update_clauses.push(SetClause {
19 column: column.to_string(),
20 value: Some(value.into()),
21 });
22 self
23 }
24
25 pub fn update_set_null(mut self, column: &str) -> Self {
27 self.update_clauses.push(SetClause {
28 column: column.to_string(),
29 value: None,
30 });
31 self
32 }
33
34 pub fn build(self) -> QueryBuilder<M> {
36 self.query_builder
39 }
40
41 pub fn to_sql_with_params(&self) -> (String, Vec<String>) {
43 let mut sql = String::new();
44 let mut params = Vec::new();
45 let mut param_counter = 1;
46
47 if let Some(table) = &self.query_builder.insert_table {
49 sql.push_str(&format!("INSERT INTO {}", table));
50
51 if !self.query_builder.set_clauses.is_empty() {
52 sql.push_str(" (");
53 let columns: Vec<String> = self.query_builder.set_clauses.iter()
54 .map(|clause| clause.column.clone())
55 .collect();
56 sql.push_str(&columns.join(", "));
57 sql.push_str(") VALUES (");
58
59 for (i, clause) in self.query_builder.set_clauses.iter().enumerate() {
60 if i > 0 {
61 sql.push_str(", ");
62 }
63 if let Some(ref value) = clause.value {
64 sql.push_str(&format!("${}", param_counter));
65 params.push(value.to_string());
66 param_counter += 1;
67 } else {
68 sql.push_str("NULL");
69 }
70 }
71 sql.push(')');
72 }
73 }
74
75 if !self.conflict_columns.is_empty() {
77 sql.push_str(&format!(" ON CONFLICT ({}) DO UPDATE SET ", self.conflict_columns.join(", ")));
78
79 for (i, clause) in self.update_clauses.iter().enumerate() {
80 if i > 0 {
81 sql.push_str(", ");
82 }
83 sql.push_str(&format!("{} = ", clause.column));
84 if let Some(ref value) = clause.value {
85 sql.push_str(&format!("${}", param_counter));
86 params.push(value.to_string());
87 param_counter += 1;
88 } else {
89 sql.push_str("NULL");
90 }
91 }
92 }
93
94 (sql, params)
95 }
96}