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 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 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 }