Skip to main content

ngb_sqlbuilder/
insert.rs

1use crate::clause::Clause;
2use crate::{wrap, Column, Final, SqlClause};
3use tokio_postgres::types::ToSql;
4
5pub struct Insert;
6pub struct End;
7pub struct OnConflictHandle<'q>(Clause<'q, End>);
8
9pub fn insert_into<'q>(
10    table: &str,
11    map: &[(&str, &'q (dyn ToSql + Sync + 'q))],
12) -> Clause<'q, Insert> {
13    let mut sql = String::from("insert into ");
14    let mut value_list = Vec::with_capacity(map.len());
15    sql.push_str(&wrap(table));
16    sql.push_str(" (");
17    let mut not_first = false;
18    for (key, value) in map {
19        if not_first {
20            sql.push(',');
21        }
22        sql.push_str(format!("\"{}\"", key).as_str());
23        not_first = true;
24        value_list.push(*value);
25    }
26    sql.push_str(") values (");
27    let mut not_first = false;
28    for _ in 0..value_list.len() {
29        if not_first {
30            sql.push(',');
31        }
32        not_first = true;
33        sql.push('$');
34    }
35    sql.push(')');
36    Clause::new(sql, value_list)
37}
38impl<'q> Clause<'q, Insert> {
39    pub fn on_conflict_do_nothing(self) -> Clause<'q, Final> {
40        let (mut sql, params) = self.get();
41        sql.push_str(" on conflict do nothing");
42        Clause::new(sql, params)
43    }
44    pub fn on_conflict(self, cols: Clause<'q, Column>) -> OnConflictHandle<'q> {
45        let (mut sql, params) = self.get();
46        let (cols_sql, _) = cols.get();
47        sql.push_str(" on conflict (");
48        sql.push_str(&cols_sql);
49        sql.push(')');
50        OnConflictHandle(Clause::new(sql, params))
51    }
52}
53
54impl<'q> OnConflictHandle<'q> {
55    pub fn do_nothing(self) -> Clause<'q, Final> {
56        let (mut sql, params) = self.0.get();
57        sql.push_str(" do nothing");
58        Clause::new(sql, params)
59    }
60
61    // pub fn do_update(self, column: Clause<'q, Column>) -> Clause<'q, Final> {
62    //     let (mut sql, params) = self.0.build();
63    //     sql.push_str(" do update ");
64    //     Clause::new(sql, params)
65    // }
66
67    pub fn do_update_excluded(self, columns: &[&str]) -> Clause<'q, Final> {
68        let (mut sql, params) = self.0.get();
69        sql.push_str(" do update set ");
70        let mut not_first = false;
71        for item in columns {
72            if not_first {
73                sql.push(',');
74            }
75            not_first = true;
76            sql.push_str(&format!("\"{}\" = excluded.\"{}\"", item, item));
77        }
78        Clause::new(sql, params)
79    }
80}
81// pub fn do_nothing<'q>() -> Clause<'q, OnConflictHandle<'q>> {
82//     Clause::new("do nothing".to_string(), Vec::new())
83// }
84// impl<'q> Clause<'q, Insert> {
85//     pub fn values_map(
86//         self,
87//         map: &HashMap<&'q str, &'q (dyn ToSql + Sync + 'q)>,
88//     ) -> Clause<'q, End> {
89//         let (mut sql, _) = self.build();
90//         let mut value_list = Vec::with_capacity(map.len());
91//         for (key, value) in map {
92//             value_list.push(*value);
93//         }
94//         Clause::new(sql, value_list)
95//     }
96//     pub fn values(self, map: &[(&str, &'q (dyn ToSql + Sync + 'q))]) -> Clause<'q, End> {
97//         let (mut sql, _) = self.build();
98//         let mut value_list = Vec::with_capacity(map.len());
99//         sql.push_str(" (");
100//         let mut not_first = false;
101//         for (key, value) in map {
102//             if not_first {
103//                 sql.push(',');
104//             }
105//             sql.push_str(format!("\"{}\"", key).as_str());
106//             not_first = true;
107//             value_list.push(*value);
108//         }
109//         sql.push_str(")");
110//         Clause::new(sql, value_list)
111//     }
112// }
113
114#[cfg(test)]
115mod tests {
116    use super::*;
117    use crate::cols;
118
119    #[test]
120    fn insert_test() {
121        let (sql, params) = insert_into("Table", &[("Col1", &1), ("Col2", &2)])
122            .on_conflict(cols(&["Test"]))
123            .do_update_excluded(&["Col1", "Col2"])
124            .get();
125        println!("{:}", sql);
126        println!("params: {:?}", params);
127    }
128}