Skip to main content

sqlink/postgres/
update_builder.rs

1use crate::error::Error;
2use crate::postgres::query_table::{QueryTables, QueryTable};
3use crate::postgres::query_field::{QueryWithParams, ParameterValueAsRef};
4use crate::postgres::query_token::{QueryTokens, QueryToken, FormatQueryTup};
5use crate::postgres::query_where::{QueryWheres, WhereOperator};
6use crate::postgres::query_set::{QuerySets};
7use crate::postgres::query_return::{QueryReturns, QueryReturnField};
8
9#[derive(Default, Debug)]
10pub struct SqlUpdate<'a> {
11    _tables: QueryTables, // to support update tableA, tableB set ...
12    _sets: QuerySets,
13    _wheres: QueryWheres,
14    _returns: QueryReturns,
15    _parameters: Vec<ParameterValueAsRef<'a>>,
16}
17
18impl<'a> SqlUpdate<'a> {
19    pub fn new() -> SqlUpdate<'static> {
20        SqlUpdate::default()
21    }
22    pub fn build(&self) -> Result<QueryWithParams, Error> {
23        let mut param_iter = 1;
24        let built_for_table = self._tables.build(&mut param_iter)?;
25        let built_for_update = self._sets.build_for_update(&mut param_iter)?;
26        let mut vec: Vec<String> = Vec::new();
27        let mut p: Vec<ParameterValueAsRef> = Vec::new();
28        for ploc in built_for_table.parameters_loc {
29            p.push(self._parameters[ploc]);
30        }
31        for ploc in built_for_update.parameters_loc {
32            p.push(self._parameters[ploc]);
33        }
34        vec.push(format!("UPDATE {} SET {}", built_for_table.query, built_for_update.query));
35        if self._wheres.len() > 0 {
36            let built_for_where = self._wheres.build(&mut param_iter)?;
37            vec.push(format!("WHERE {}", built_for_where.query));
38            for ploc in built_for_where.parameters_loc {
39                p.push(self._parameters[ploc]);
40            }
41        }
42        if self._returns.len() > 0 {
43            let built_for_return: String = self._returns.build()?;
44            vec.push(format!("RETURNING {}", built_for_return));
45        }
46
47        Ok(QueryWithParams {
48            query: vec.join(" "),
49            parameters: p,
50        })
51    }
52    pub fn table<S: Into<QueryTable>>(&mut self, table: S) -> &mut Self {
53        self._tables.push(table.into());
54        self
55    }
56    pub fn set<S: Into<String>, T>(&mut self, field: S, param: &'a T) -> &mut Self where T: postgres_types::ToSql + std::marker::Sync + 'a {
57        self._parameters.push(param);
58        self._sets.set((field.into(), QueryTokens(vec![QueryToken::ParameterLoc(self._parameters.len() - 1)])));
59        self
60    }
61    pub fn set_raw<S: Into<String>>(&mut self, field: S, tup: FormatQueryTup<'a>) -> &mut Self{
62        let len = self._parameters.len();
63        self._parameters.extend(tup.1);
64        let qtokens = (tup.0).to_query_tokens(len);
65        self._sets.set((field.into(), qtokens));
66        self
67    }
68    pub fn returning<S: Into<QueryReturnField>>(&mut self, field: S) -> &mut Self {
69        self._returns.push(field.into());
70        self
71    }
72    pub fn and_where(&mut self, ftup: FormatQueryTup<'a>) -> &mut Self {
73        if self._wheres.len() > 0 {
74            self._wheres.push(WhereOperator::And);
75        }
76        let len = self._parameters.len();
77        self._parameters.extend(ftup.1);
78        let qtokens = (ftup.0).to_query_tokens(len);
79        self._wheres.extend(qtokens.into());
80        self
81    }
82    pub fn or_where(&mut self, ftup: FormatQueryTup<'a>) -> &mut Self {
83        if self._wheres.len() > 0 {
84            self._wheres.push(WhereOperator::Or);
85        }
86        let len = self._parameters.len();
87        self._parameters.extend(ftup.1);
88        let qtokens = (ftup.0).to_query_tokens(len);
89        self._wheres.extend(qtokens.into());
90        self
91    }
92    pub fn and_where_open(&mut self) -> &mut Self {
93        if self._wheres.len() > 0 {
94            self._wheres.push(WhereOperator::And);
95        }
96        self._wheres.push(WhereOperator::Open);
97        self
98    }
99    pub fn or_where_open(&mut self) -> &mut Self {
100        if self._wheres.len() > 0 {
101            self._wheres.push(WhereOperator::Or);
102        }
103        self._wheres.push(WhereOperator::Open);
104        self
105    }
106    pub fn where_close(&mut self) -> &mut Self {
107        self._wheres.push(WhereOperator::Close);
108        // lets dont panic, if error database will panic
109        self
110    }
111    pub fn inner_join<S: Into<QueryTable>>(&mut self, query_table: S, ftup: FormatQueryTup<'a>) -> &mut Self {
112        let len = self._parameters.len();
113        self._parameters.extend(ftup.1);
114        let qtokens = (ftup.0).to_query_tokens(len);
115        self._tables.inner_join(query_table.into());
116        self._tables.on(qtokens.into());
117        self
118    }
119    pub fn left_join<S: Into<QueryTable>>(&mut self, query_table: S, ftup: FormatQueryTup<'a>) -> &mut Self {
120        let len = self._parameters.len();
121        self._parameters.extend(ftup.1);
122        let qtokens = (ftup.0).to_query_tokens(len);
123        self._tables.left_join(query_table.into());
124        self._tables.on(qtokens.into());
125        self
126    }
127    pub fn right_join<S: Into<QueryTable>>(&mut self, query_table: S, ftup: FormatQueryTup<'a>) -> &mut Self {
128        let len = self._parameters.len();
129        self._parameters.extend(ftup.1);
130        let qtokens = (ftup.0).to_query_tokens(len);
131        self._tables.right_join(query_table.into());
132        self._tables.on(qtokens.into());
133        self
134    }
135    pub fn full_join<S: Into<QueryTable>>(&mut self, query_table: S, ftup: FormatQueryTup<'a>) -> &mut Self {
136        let len = self._parameters.len();
137        self._parameters.extend(ftup.1);
138        let qtokens = (ftup.0).to_query_tokens(len);
139        self._tables.full_join(query_table.into());
140        self._tables.on(qtokens.into());
141        self
142    }
143}
144
145#[cfg(test)]
146mod tests {
147    use crate::postgres::query_token::{format_query};
148    use super::*;
149    #[test]
150    fn test_update_builder_1() {
151        let mut sqlupdate = SqlUpdate::new();
152        let qbuild = sqlupdate
153            .table("user")
154            .set("age", &1337)
155            .set_raw("name", format_query("LOWER({})".to_owned(), vec![&("foo")]))
156            .and_where(format_query("id = {}".to_owned(), vec![&(1)]))
157            .build().unwrap();
158        assert_eq!(qbuild.query, "UPDATE \"user\" SET \"age\"=$1,\"name\"=LOWER($2) WHERE id = $3");
159        assert_eq!(format!("{:?}", qbuild.parameters), "[1337, \"foo\", 1]");
160    }
161}