Skip to main content

ngb_sqlbuilder/
clause.rs

1use crate::{Build, SqlClause};
2use std::marker::PhantomData;
3use tokio_postgres::types::ToSql;
4
5#[derive(Debug, Clone)]
6pub struct Clause<'q, T> {
7    pub(crate) sql: String,
8    pub(crate) params: Vec<&'q (dyn ToSql + Sync)>,
9    _ph: PhantomData<T>,
10}
11impl<'q, T> Clause<'q, T> {
12    pub(crate) fn new(sql: String, params: Vec<&'q (dyn ToSql + Sync)>) -> Self {
13        Self {
14            sql,
15            params,
16            _ph: PhantomData,
17        }
18    }
19    // pub fn alias(mut self, name: &str) -> Self {
20    //     self.sql.push_str(format!(" as \"{}\"", name).as_str());
21    //     self
22    // }
23
24    pub fn this(self) -> Self {
25        self
26    }
27
28    pub fn into<C>(self) -> Clause<'q, C> {
29        Clause::new(self.sql, self.params)
30    }
31    pub fn combine_raw(self, raw_sql: &str, params: &[&'q (dyn ToSql + Sync)]) -> Self {
32        let (mut s, mut p) = self.unwrap();
33        s.push(' ');
34        s.push_str(&raw_sql.trim());
35        p.extend_from_slice(params);
36        Self::new(s, p)
37    }
38}
39
40impl<'q, T> Build<'q> for Clause<'q, T> {
41    /// Build and compile query into SQL syntax with numbered parameters
42    fn build(self) -> (String, Vec<&'q (dyn ToSql + Sync)>) {
43        let init_capacity = self.sql.len() + self.params.len();
44        let mut result = String::with_capacity(init_capacity);
45        let mut start = 0;
46        let mut count = 1;
47        for (i, _) in self.sql.match_indices("$") {
48            result.push_str(&self.sql[start..i]);
49            result.push_str(&format!("${count}"));
50            count += 1;
51            start = i + 1;
52        }
53        result.push_str(&self.sql[start..]);
54        (result, self.params)
55    }
56    // fn build_as_ref(&self) -> (&str, &[&'q (dyn ToSql + Sync)]) {
57    //     todo!()
58    // }
59}