1use crate::{Build, SqlClause};
2use std::fmt::{Debug, Display, Formatter};
3use std::marker::PhantomData;
4use tokio_postgres::types::ToSql;
5
6pub struct Clause<'q, T> {
8 pub(crate) sql: String,
9 pub(crate) params: Vec<&'q (dyn ToSql + Sync)>,
10 _ph: PhantomData<T>,
11}
12
13pub trait ToClause<'q> {
14 fn to_clause<C>(self) -> Clause<'q, C>;
15}
16impl<'q> ToClause<'q> for &str {
17 fn to_clause<C>(self) -> Clause<'q, C> {
18 Clause::new(String::from(self), vec![])
19 }
20}
21impl<T> Clone for Clause<'_, T> {
22 fn clone(&self) -> Self {
23 Self {
24 sql: self.sql.clone(),
25 params: self.params.clone(),
26 _ph: PhantomData,
27 }
28 }
29}
30impl<'q, T> Clause<'q, T> {
31 pub(crate) fn new(sql: String, params: Vec<&'q (dyn ToSql + Sync)>) -> Self {
32 Self {
33 sql,
34 params,
35 _ph: PhantomData,
36 }
37 }
38 pub fn this(self) -> Self {
44 self
45 }
46
47 pub fn into<C>(self) -> Clause<'q, C> {
49 Clause::new(self.sql, self.params)
50 }
51 pub fn combine_raw(self, raw_sql: &str, params: &[&'q (dyn ToSql + Sync)]) -> Self {
52 let (mut s, mut p) = self.unwrap();
53 s.push(' ');
54 s.push_str(&raw_sql.trim());
55 p.extend_from_slice(params);
56 Self::new(s, p)
57 }
58
59 pub fn debug(self) -> Self {
61 println!("{:?}", &self);
62 self
63 }
64}
65
66impl<'q, T> Build<'q> for Clause<'q, T> {
73 fn build(self) -> (String, Vec<&'q (dyn ToSql + Sync)>) {
75 (__build_sql(&self.sql, self.params.len()), self.params)
87 }
88 }
96impl<'q, T> Display for Clause<'q, T> {
97 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
98 let sql = __build_sql(&self.sql, self.params.len());
99 write!(f, "{}", &sql)
100 }
101}
102impl<'q, T> Debug for Clause<'q, T> {
103 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
104 write!(f, "{}", self)
105 }
106}
107fn __build_sql(sql: &str, params_len: usize) -> String {
108 let mut result = String::with_capacity(sql.len() + params_len);
110 let mut start = 0;
111 let mut count = 1;
112 for (i, _) in sql.match_indices("$") {
113 result.push_str(&sql[start..i]);
114 result.push_str(&format!("${count}"));
115 count += 1;
116 start = i + 1;
117 }
118 result.push_str(&sql[start..]);
119 result
120}