karbon_framework/db/
query.rs1use super::PaginationParams;
2use super::placeholder;
3
4pub struct QueryBuilder {
17 table: String,
18 alias: String,
19 columns: String,
20 joins: Vec<String>,
21 conditions: Vec<String>,
22 search_cols: Vec<String>,
23 group_by: Option<String>,
24}
25
26impl QueryBuilder {
27 pub fn select(table: &str) -> Self {
28 Self {
29 table: table.to_string(),
30 alias: String::new(),
31 columns: "*".to_string(),
32 joins: Vec::new(),
33 conditions: Vec::new(),
34 search_cols: Vec::new(),
35 group_by: None,
36 }
37 }
38
39 pub fn columns(mut self, cols: &str) -> Self {
40 self.columns = cols.to_string();
41 self
42 }
43
44 pub fn alias(mut self, alias: &str) -> Self {
45 self.alias = alias.to_string();
46 self
47 }
48
49 pub fn join(mut self, join: &str) -> Self {
50 self.joins.push(join.to_string());
51 self
52 }
53
54 pub fn where_clause(mut self, condition: &str) -> Self {
55 self.conditions.push(condition.to_string());
56 self
57 }
58
59 pub fn where_if(mut self, condition: &str, apply: bool) -> Self {
60 if apply {
61 self.conditions.push(condition.to_string());
62 }
63 self
64 }
65
66 pub fn search_columns(mut self, cols: &[&str]) -> Self {
67 self.search_cols = cols.iter().map(|s| s.to_string()).collect();
68 self
69 }
70
71 pub fn group_by(mut self, clause: &str) -> Self {
72 self.group_by = Some(clause.to_string());
73 self
74 }
75
76 pub fn paginate(&self, params: &PaginationParams) -> (String, String) {
81 let from = if self.alias.is_empty() {
82 self.table.clone()
83 } else {
84 format!("{} {}", self.table, self.alias)
85 };
86
87 let joins = self.joins.join(" ");
88
89 let mut where_parts = self.conditions.clone();
90
91 if params.search.is_some() && !self.search_cols.is_empty() {
93 let search_cond = self
94 .search_cols
95 .iter()
96 .enumerate()
97 .map(|(i, c)| format!("{} LIKE {}", c, placeholder(i + 1)))
98 .collect::<Vec<_>>()
99 .join(" OR ");
100 where_parts.push(format!("({})", search_cond));
101 }
102
103 let where_clause = if where_parts.is_empty() {
104 String::new()
105 } else {
106 format!(" WHERE {}", where_parts.join(" AND "))
107 };
108
109 let group = self
110 .group_by
111 .as_ref()
112 .map(|g| format!(" GROUP BY {}", g))
113 .unwrap_or_default();
114
115 let sort = params.sort_column(&[], "id");
116 let order = params.order_direction();
117
118 let data_query = format!(
119 "SELECT {} FROM {} {}{}{} ORDER BY {} {} LIMIT {} OFFSET {}",
120 self.columns,
121 from,
122 joins,
123 where_clause,
124 group,
125 sort,
126 order,
127 params.safe_per_page(),
128 params.offset()
129 );
130
131 let count_query = format!(
132 "SELECT COUNT(*) as count FROM {} {}{}{}",
133 from, joins, where_clause, group
134 );
135
136 (data_query, count_query)
137 }
138}