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 union<C>(self, clause: Clause<'q, C>) -> Clause<'q, ()> {
60 let (mut sql, mut params) = self.unwrap();
61 let (cl_sql, cl_params) = clause.unwrap();
62 sql.push_str(" UNION ");
63 sql.push_str(&cl_sql);
64 params.extend_from_slice(&cl_params);
65 Clause::new(sql, params)
66 }
67 pub fn union_all<C>(self, clause: Clause<'q, C>) -> Clause<'q, ()> {
68 let (mut sql, mut params) = self.unwrap();
69 let (cl_sql, cl_params) = clause.unwrap();
70 sql.push_str(" UNION ALL ");
71 sql.push_str(&cl_sql);
72 params.extend_from_slice(&cl_params);
73 Clause::new(sql, params)
74 }
75
76 pub fn debug(self) -> Self {
78 println!("{:?}", &self);
79 self
80 }
81}
82
83impl<'q, T> Build<'q> for Clause<'q, T> {
90 fn build(self) -> (String, Vec<&'q (dyn ToSql + Sync)>) {
92 (__build_sql(&self.sql, self.params.len()), self.params)
104 }
105 }
113impl<'q, T> Display for Clause<'q, T> {
114 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
115 let sql = __build_sql(&self.sql, self.params.len());
116 write!(f, "{}", &sql)
117 }
118}
119impl<'q, T> Debug for Clause<'q, T> {
120 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
121 write!(f, "{}", self)
122 }
123}
124fn __build_sql(sql: &str, params_len: usize) -> String {
125 let mut result = String::with_capacity(sql.len() + params_len);
127 let mut start = 0;
128 let mut count = 1;
129 for (i, _) in sql.match_indices("$") {
130 result.push_str(&sql[start..i]);
131 result.push_str(&format!("${count}"));
132 count += 1;
133 start = i + 1;
134 }
135 result.push_str(&sql[start..]);
136 result
137}