Skip to main content

ngb_sqlbuilder/
lib.rs

1use crate::select::Clause;
2use tokio_postgres::types::ToSql;
3
4// type Parameter = (dyn ToSql + Sync);
5
6mod builder;
7mod clause;
8mod condition;
9mod insert;
10#[allow(dead_code)]
11mod select;
12mod update;
13
14// pub use builder::*;
15// pub use clause::*;
16// pub use condition::*;
17pub use insert::*;
18pub use update::*;
19pub use select::*;
20
21pub struct Raw;
22// #[derive(Debug)]
23pub struct Column;
24// #[derive(Debug)]
25pub struct Select;
26// #[derive(Debug)]
27pub struct From;
28// #[derive(Debug)]
29pub struct Table;
30// #[derive(Debug)]
31pub struct Final;
32// #[derive(Debug)]
33pub struct Join;
34// #[derive(Debug)]
35
36// #[derive(Debug)]
37pub struct Condition;
38// #[derive(Debug)]
39pub struct Paging;
40
41trait SqlClause<'q> {
42    fn get(self) -> (String, Vec<&'q (dyn ToSql + Sync)>);
43}
44// trait SqlCondition<'q> {
45//     fn new(sql: String, params: Vec<&'q (dyn ToSql + Sync)>) -> Self;
46//     // fn build(self) -> (String, Vec<&'q (dyn ToSql + Sync)>);
47// }
48fn format_col(name: &str) -> String {
49    match name.chars().position(|c| c == '.') {
50        Some(dot) => format!("{}.\"{}\"", &name[..dot], name[dot + 1..].trim()),
51        None => format!("\"{}\"", name),
52    }
53}
54fn format_prim(name: &str) -> String {
55    let (col, alias) = {
56        let mut split_as = name.split(" as ");
57        let col_name = split_as.next().unwrap_or_default();
58        let alias = split_as.next();
59        (col_name, alias)
60    };
61
62    let mut col_name = format_col(col);
63
64    if let Some(a) = alias {
65        if a.chars().any(char::is_uppercase) {
66            col_name.push_str(&format!(" as \"{}\"", a));
67        } else {
68            col_name.push_str(&format!(" as {}", a));
69        }
70    }
71    col_name
72}
73fn __cols(sql: &mut String, columns: &[&str]) {
74    let mut not_first = false;
75    for col in columns {
76        if not_first {
77            sql.push_str(", ");
78        }
79        not_first = true;
80        sql.push_str(&format_prim(col));
81    }
82}
83pub fn cols<'q>(columns: &[&str]) -> Clause<'q, Column> {
84    let mut sql = String::new();
85    __cols(&mut sql, columns);
86    Clause::new(sql, vec![])
87}
88fn wrap(s: &str) -> String {
89    format!("\"{}\"", s)
90}
91pub fn op<'q, T: ToSql + Sync + 'q>(op: &str, value: &'q T) -> Clause<'q, Condition> {
92    Clause::<Condition>::new(format!(" {op} $"), vec![value])
93}
94
95pub fn eq<'q, T: ToSql + Sync + 'q>(value: &'q T) -> Clause<'q, Condition> {
96    op("=", value)
97}
98
99pub fn lt<'q, T: ToSql + Sync + 'q>(value: &'q T) -> Clause<'q, Condition> {
100    op("<", value)
101}
102
103pub fn gt<'q, T: ToSql + Sync + 'q>(value: &'q T) -> Clause<'q, Condition> {
104    op(">", value)
105}
106
107pub fn lte<'q, T: ToSql + Sync + 'q>(value: &'q T) -> Clause<'q, Condition> {
108    op("<=", value)
109}
110
111pub fn gte<'q, T: ToSql + Sync + 'q>(value: &'q T) -> Clause<'q, Condition> {
112    op(">=", value)
113}
114pub fn like<'q, T: ToSql + Sync + 'q>(value: &'q T) -> Clause<'q, Condition> {
115    op("like", value)
116}
117pub fn ilike<'q, T: ToSql + Sync + 'q>(value: &'q T) -> Clause<'q, Condition> {
118    op("ilike", value)
119}
120
121pub fn between<'q, T: ToSql + Sync + 'q>(low: &'q T, high: &'q T) -> Clause<'q, Condition> {
122    Clause::new(" between $ and $".to_string(), vec![low, high])
123    // Clause {
124    //     sql: " between $ and $".to_string(),
125    //     params: vec![low, high],
126    //     _ph: PhantomData,
127    // }
128}
129
130pub fn raw<'q, T>(sql: &str, values: &[&'q (dyn ToSql + Sync)]) -> Clause<'q, T> {
131    Clause::new(sql.to_string(), values.to_vec())
132}