1use tokio_postgres::types::ToSql;
2
3mod builder;
6mod clause;
7mod condition;
8mod delete;
9mod insert;
10#[allow(dead_code)]
11mod select;
12mod update;
13
14mod column;
15#[cfg(feature = "execution")]
16pub mod execution;
17
18pub use clause::*;
20pub use condition::*;
21pub use delete::*;
22pub use insert::*;
23pub use select::*;
24pub use update::*;
25pub struct Raw;
28pub struct Column;
30pub struct Select;
32pub struct From;
34pub struct Table;
36pub struct Join;
40pub struct Condition;
41pub struct Paging;
42
43pub trait SqlClause<'q> {
44 fn unwrap(self) -> (String, Vec<&'q (dyn ToSql + Sync)>);
45 fn unwrap_ref(&self) -> (&str, &[&'q (dyn ToSql + Sync)]);
46}
47pub trait Build<'q> {
48 fn build(self) -> (String, Vec<&'q (dyn ToSql + Sync)>);
49 }
52
53fn format_col(name: &str) -> String {
54 let mut cast_split = name.split("::");
55 let name = cast_split.next().unwrap_or_default();
56 let mut result = match name.chars().position(|c| c == '.') {
57 Some(dot) => format!("{}.\"{}\"", &name[..dot], name[dot + 1..].trim()),
58 None => format!("\"{}\"", name),
59 };
60 if let Some(cast) = cast_split.next() {
61 result.push_str("::");
62 result.push_str(&cast);
63 }
65 result
66}
67fn append_wrap(sql: &mut String, value: &str) {
68 sql.push('"');
69 sql.push_str(value);
70 sql.push('"');
71}
72fn append_col(sql: &mut String, expr: &str) {
73 let mut cast_split = expr.split("::");
74 let name = cast_split.next().unwrap_or_default();
75 match name.chars().position(|c| c == '.') {
76 Some(dot) => {
77 sql.push_str(&name[..dot]);
78 sql.push('.');
79 append_wrap(sql, &name[dot + 1..]);
80 }
82 None => {
83 append_wrap(sql, name);
84 }
86 };
87 if let Some(cast) = cast_split.next() {
88 sql.push_str("::");
89 sql.push_str(cast);
90 }
92}
93fn split_alias(value: &str) -> (&str, Option<&str>) {
94 let mut split_as = value.split(" as ");
95 let col_name = split_as.next().unwrap_or_default();
96 let alias = split_as.next();
97 (col_name, alias)
98}
99fn format_prim(expr: &str) -> String {
100 let (col, alias) = split_alias(expr.trim());
108
109 let mut col_name = format_col(col);
110
111 if let Some(a) = alias {
112 col_name.push(' ');
114 if a.chars().any(char::is_uppercase) {
115 col_name.push_str(&wrap(a));
116 } else {
118 col_name.push_str(&a);
119 }
121 }
122 col_name
123}
124fn append_prim(sql: &mut String, expr: &str) {
125 let (col, alias) = split_alias(expr.trim());
126
127 append_col(sql, col.trim());
128
129 if let Some(a) = alias {
130 sql.push(' ');
132 if a.chars().any(char::is_uppercase) {
133 append_wrap(sql, a.trim());
134 } else {
135 sql.push_str(a.trim());
136 }
137 }
138}
139fn __cols(sql: &mut String, columns: &[&str]) {
140 let mut not_first = false;
141 for col in columns {
142 if not_first {
143 sql.push_str(", ");
144 }
145 not_first = true;
146 append_prim(sql, col);
147 }
149}
150pub fn cols<'q>(columns: &[&str]) -> Clause<'q, Column> {
151 let mut sql = String::new();
152 __cols(&mut sql, columns);
153 Clause::new(sql, vec![])
154}
155pub fn func<'q, T, C>(name: &str, clause: Clause<'q, T>) -> Clause<'q, C> {
156 let mut sql = String::from(name);
157 let (cl_sql, cl_params) = clause.unwrap();
158 sql.push('(');
159 sql.push_str(&cl_sql);
160 sql.push(')');
161 Clause::new(sql, cl_params)
162}
163pub fn func_col<'q>(func_name: &str, column: &str) -> Clause<'q, Column> {
164 func(func_name, col(column))
165}
166pub fn avg_col(column: &str) -> Clause<'_, Column> {
167 func("avg", col(column))
168}
169pub fn max_col(column: &str) -> Clause<'_, Column> {
170 func("max", col(column))
171}
172pub fn min_col(column: &str) -> Clause<'_, Column> {
173 func("min", col(column))
174}
175pub fn sum_col(column: &str) -> Clause<'_, Column> {
176 func("sum", col(column))
177}
178fn wrap(s: &str) -> String {
179 format!("\"{}\"", s)
180}
181pub fn extract_col<'q>(field: &str, from: &str) -> Clause<'q, Column> {
182 let mut sql = String::from("extract(");
183 sql.push_str(field);
184 sql.push_str(" from ");
185 sql.push_str(&format_col(from));
186 sql.push(')');
187 Clause::new(sql, vec![])
188}
189
190pub fn raw<'q, T>(sql: &str, values: &[&'q (dyn ToSql + Sync)]) -> Clause<'q, T> {
191 Clause::new(sql.to_string(), values.to_vec())
192}
193
194fn __and_col<'q, T>(
195 clause: Clause<'q, T>,
196 name: &str,
197 condition: Clause<'q, Condition>,
198) -> Clause<'q, T> {
199 let (mut sql, mut params) = clause.unwrap();
200 let (cond_sql, cond_params) = condition.unwrap();
201 sql.push_str(" AND ");
202 append_col(&mut sql, name);
204 sql.push_str(&cond_sql);
205 params.extend(cond_params);
206 Clause::new(sql, params)
207}
208fn __or_col<'q, T>(
209 clause: Clause<'q, T>,
210 name: &str,
211 condition: Clause<'q, Condition>,
212) -> Clause<'q, T> {
213 let (mut sql, mut params) = clause.unwrap();
214 let (cond_sql, cond_params) = condition.unwrap();
215 sql.push_str(" OR ");
216 append_col(&mut sql, name);
218 sql.push_str(&cond_sql);
219 params.extend(cond_params);
220 Clause::new(sql, params)
221}
222
223fn __and_nest<'q, T1, T2, R>(clause: Clause<'q, T1>, condition: Clause<'q, T2>) -> Clause<'q, R> {
241 let (mut sql, mut params) = clause.unwrap();
242 sql.push_str(" AND (");
243 sql.push_str(&condition.sql);
244 sql.push(')');
245 params.extend(condition.params);
246 Clause::new(sql, params)
247}
248fn __or_nest<'q, T1, T2, R>(clause: Clause<'q, T1>, condition: Clause<'q, T2>) -> Clause<'q, R> {
249 let (mut sql, mut params) = clause.unwrap();
250 sql.push_str(" OR (");
251 sql.push_str(&condition.sql);
252 sql.push(')');
253 params.extend(condition.params);
254 Clause::new(sql, params)
255}
256fn __condition<'q, T, C>(
257 connector: &str,
258 clause: Clause<'q, T>,
259 condition: Clause<'q, Condition>,
260) -> Clause<'q, C> {
261 let (mut sql, mut params) = clause.unwrap();
262 let (cond_sql, cond_params) = condition.unwrap();
263 sql.push_str(connector);
264 sql.push_str(&cond_sql);
265 params.extend_from_slice(&cond_params);
266 Clause::new(sql, params)
267}
268
269const LOGIC_CONN_NONE: &str = "";
270const LOGIC_CONN_AND: &str = " AND ";
271const LOGIC_CONN_OR: &str = " OR ";