1use crate::select::Clause;
2use tokio_postgres::types::ToSql;
3
4mod builder;
7mod clause;
8mod condition;
9mod delete;
10mod insert;
11#[allow(dead_code)]
12mod select;
13mod update;
14
15pub use insert::*;
19pub use select::*;
20pub use update::*;
21pub use delete::*;
22
23pub struct Raw;
24pub struct Column;
26pub struct Select;
28pub struct From;
30pub struct Table;
32pub struct Join;
36pub struct Condition;
40pub struct Paging;
42
43trait SqlClause<'q> {
44 fn unwrap(self) -> (String, Vec<&'q (dyn ToSql + Sync)>);
45}
46impl<'q> Clause<'q, Column> {
47 pub fn eq(self) -> Clause<'q, Condition> {
48 todo!()
49 }
50}
51fn format_col(name: &str) -> String {
52 match name.chars().position(|c| c == '.') {
53 Some(dot) => format!("{}.\"{}\"", &name[..dot], name[dot + 1..].trim()),
54 None => format!("\"{}\"", name),
55 }
56}
57fn format_prim(name: &str) -> String {
58 let (col, alias) = {
59 let mut split_as = name.split(" as ");
60 let col_name = split_as.next().unwrap_or_default();
61 let alias = split_as.next();
62 (col_name, alias)
63 };
64
65 let mut col_name = format_col(col);
66
67 if let Some(a) = alias {
68 if a.chars().any(char::is_uppercase) {
69 col_name.push_str(&format!(" as \"{}\"", a));
70 } else {
71 col_name.push_str(&format!(" as {}", a));
72 }
73 }
74 col_name
75}
76fn __cols(sql: &mut String, columns: &[&str]) {
77 let mut not_first = false;
78 for col in columns {
79 if not_first {
80 sql.push_str(", ");
81 }
82 not_first = true;
83 sql.push_str(&format_prim(col));
84 }
85}
86pub fn cols<'q>(columns: &[&str]) -> Clause<'q, Column> {
87 let mut sql = String::new();
88 __cols(&mut sql, columns);
89 Clause::new(sql, vec![])
90}
91fn wrap(s: &str) -> String {
92 format!("\"{}\"", s)
93}
94pub fn op<'q, T: ToSql + Sync + 'q>(op: &str, value: &'q T) -> Clause<'q, Condition> {
95 Clause::<Condition>::new(format!(" {op} $"), vec![value])
96}
97pub fn eq<'q, T: ToSql + Sync + 'q>(value: &'q T) -> Clause<'q, Condition> {
98 op("=", value)
99}
100
101pub fn lt<'q, T: ToSql + Sync + 'q>(value: &'q T) -> Clause<'q, Condition> {
102 op("<", value)
103}
104
105pub fn gt<'q, T: ToSql + Sync + 'q>(value: &'q T) -> Clause<'q, Condition> {
106 op(">", value)
107}
108
109pub fn lte<'q, T: ToSql + Sync + 'q>(value: &'q T) -> Clause<'q, Condition> {
110 op("<=", value)
111}
112
113pub fn gte<'q, T: ToSql + Sync + 'q>(value: &'q T) -> Clause<'q, Condition> {
114 op(">=", value)
115}
116pub fn like<'q, T: ToSql + Sync + 'q>(value: &'q T) -> Clause<'q, Condition> {
117 op("like", value)
118}
119pub fn ilike<'q, T: ToSql + Sync + 'q>(value: &'q T) -> Clause<'q, Condition> {
120 op("ilike", value)
121}
122
123pub fn between<'q, T: ToSql + Sync + 'q>(low: &'q T, high: &'q T) -> Clause<'q, Condition> {
124 Clause::new(" between $ and $".to_string(), vec![low, high])
125}
126
127pub fn raw<'q, T>(sql: &str, values: &[&'q (dyn ToSql + Sync)]) -> Clause<'q, T> {
128 Clause::new(sql.to_string(), values.to_vec())
129}
130
131fn __and<'q, T>(
132 clause: Clause<'q, T>,
133 name: &str,
134 condition: Clause<'q, Condition>,
135) -> Clause<'q, T> {
136 let (mut sql, mut params) = clause.unwrap();
137 let (cond_sql, cond_params) = condition.unwrap();
138 sql.push_str(" AND ");
139 sql.push_str(&format_col(name));
140 sql.push_str(cond_sql.as_str());
141 params.extend(cond_params);
142 Clause::new(sql, params)
143}
144fn __or<'q, T>(
145 clause: Clause<'q, T>,
146 name: &str,
147 condition: Clause<'q, Condition>,
148) -> Clause<'q, T> {
149 let (mut sql, mut params) = clause.unwrap();
150 let (cond_sql, cond_params) = condition.unwrap();
151 sql.push_str(" OR ");
152 sql.push_str(&format_col(name));
153 sql.push_str(cond_sql.as_str());
154 params.extend(cond_params);
155 Clause::new(sql, params)
156}
157
158fn __and_wrap<'q, T>(clause: Clause<'q, T>, condition: Clause<'q, Where>) -> Clause<'q, Where> {
159 let (mut sql, mut params) = clause.unwrap();
160 sql.push_str(" AND (");
161 sql.push_str(&condition.sql);
162 sql.push(')');
163 params.extend(condition.params);
164 Clause::new(sql, params)
165}
166fn __or_wrap<'q, T>(clause: Clause<'q, T>, condition: Clause<'q, Where>) -> Clause<'q, Where> {
167 let (mut sql, mut params) = clause.unwrap();
168 sql.push_str(" OR (");
169 sql.push_str(&condition.sql);
170 sql.push(')');
171 params.extend(condition.params);
172 Clause::new(sql, params)
173}