degen_sql/
sql_builder.rs

1
2
3use std::sync::Arc;
4use std::collections::BTreeMap;
5
6use tokio_postgres::types::ToSql;
7
8pub struct SqlBuilder {
9
10	pub statement_base: SqlStatementBase,
11	pub table_name : String, 
12	pub where_params: BTreeMap<String, Arc<dyn ToSql + Sync> > , 
13
14	pub order: Option<(String,OrderingDirection)> , 
15
16	pub limit: Option< u32 >, 
17
18
19}
20
21impl SqlBuilder {
22    pub fn build(&self) -> (String , Vec<Arc<dyn ToSql + Sync>>  ) {
23        let mut query = format!("{} FROM {}", self.statement_base.build(), self.table_name);
24        let mut conditions = Vec::new();
25        let mut params: Vec<Arc<dyn ToSql + Sync>> = Vec::new();
26
27        // WHERE conditions
28        for (key, param) in &self.where_params {
29            params.push(Arc::clone(param)); // Clone Arc reference
30            conditions.push(format!("{} = ${}", key, params.len()));
31        }
32
33        if !conditions.is_empty() {
34            query.push_str(" WHERE ");
35            query.push_str(&conditions.join(" AND "));
36        }
37
38        // ORDER BY clause
39        if let Some((column, direction)) = &self.order {
40            query.push_str(&format!(" ORDER BY {} {}", column, direction.build()));
41        }
42
43        // LIMIT clause
44        if let Some(limit) = self.limit {
45            query.push_str(&format!(" LIMIT {}", limit));
46        }
47
48        ( query , params) 
49    }
50}
51
52
53
54pub enum SqlStatementBase {
55	SelectAll,
56}
57
58impl SqlStatementBase {
59
60	pub fn build(&self) -> String {
61
62		match self {
63
64			Self::SelectAll => "SELECT *" 
65
66		}.to_string() 
67	}
68
69}
70
71pub enum OrderingDirection {
72
73	DESC,
74	ASC 
75}
76
77
78impl OrderingDirection {
79
80	pub fn build(&self) -> String {
81
82		match self {
83
84			Self::DESC => "DESC" ,
85			Self::ASC => "ASC" 
86
87		}.to_string() 
88	}
89
90}
91
92
93#[cfg(test)]
94mod tests {
95    use super::*;
96    use std::collections::HashMap;
97    use std::sync::Arc;
98   // use rust_decimal::Decimal;
99
100    #[test]
101    fn test_sql_builder() {
102        let mut where_params: HashMap<String, Arc<dyn ToSql + Sync>> = HashMap::new();
103        where_params.insert("chain_id".to_string(), Arc::new(1_i64));
104        where_params.insert("status".to_string(), Arc::new("active".to_string()));
105
106        let sql_builder = SqlBuilder {
107            statement_base: SqlStatementBase::SelectAll,
108            table_name: "teller_bids".to_string(),
109            where_params,
110            order: Some(("created_at".to_string(), OrderingDirection::DESC)),
111            limit: Some(10),
112        };
113
114        let (query,params) = sql_builder.build();
115
116        assert_eq!(
117            query,
118            "SELECT * FROM teller_bids WHERE chain_id = $1 AND status = $2 ORDER BY created_at DESC LIMIT 10"
119        );
120
121         assert_eq!(
122            params.len(),
123             2
124        );
125    }
126}