1use crate::error::Error;
2use crate::postgres::query_field::{QueryWithParamsLoc};
3use crate::postgres::query_where::{QueryWheres, WhereOperator};
4use crate::postgres::static_constant::TABLE_ESCAPE;
5
6#[derive(Debug)]
7pub struct QueryTables(Vec<QueryTable>);
8
9impl Default for QueryTables {
10 fn default() -> Self {
11 QueryTables(Vec::new())
12 }
13}
14
15impl QueryTables {
16 pub fn len(&self) -> usize {
17 self.0.len()
18 }
19 pub fn build(&self, i: &mut i8) -> Result<QueryWithParamsLoc, Error> {
20 if self.0.len() != 1 {
21 return Err(Error::Syntax("Table can only select 1 time".into()));
22 }
23 let mut v: Vec<String> = Vec::new();
24 let mut q: Vec<usize> = Vec::new();
25 for join in &self.0 {
26 let built = join.build(i)?;
27 v.push(built.query);
28 q.extend(built.parameters_loc);
29 }
30 Ok(QueryWithParamsLoc {
31 query: v.join(","),
32 parameters_loc: q,
33 })
34 }
35 pub fn push(&mut self, field: QueryTable) {
36 self.0.push(field);
37 }
38 pub fn get_last_table(&mut self) -> &mut QueryTable {
39 let len = self.0.len();
40 if len == 0 {
41 panic!("cannot select without base table");
42 }
43 &mut self.0[len - 1]
44 }
45 pub fn inner_join(&mut self, query_table: QueryTable) -> &mut Self {
46 let table = self.get_last_table();
47 table.table_join.push(TableJoin::InnerJoin(query_table, QueryWheres::default()));
48 self
49 }
50 pub fn left_join(&mut self, query_table: QueryTable) -> &mut Self {
51 let table = self.get_last_table();
52 table.table_join.push(TableJoin::LeftJoin(query_table, QueryWheres::default()));
53 self
54 }
55 pub fn right_join(&mut self, query_table: QueryTable) -> &mut Self {
56 let table = self.get_last_table();
57 table.table_join.push(TableJoin::RightJoin(query_table, QueryWheres::default()));
58 self
59 }
60 pub fn full_join(&mut self, query_table: QueryTable) -> &mut Self {
61 let table = self.get_last_table();
62 table.table_join.push(TableJoin::FullJoin(query_table, QueryWheres::default()));
63 self
64 }
65 pub fn on(&mut self, query_where: QueryWheres) -> &mut Self {
66 let table = self.get_last_table();
67 let len = table.table_join.len();
68 if len == 0 {
69 panic!("cannot on without join table");
70 }
71 let w = match &mut table.table_join[len - 1] {
72 TableJoin::InnerJoin(_, w) => w,
73 TableJoin::LeftJoin(_, w) => w,
74 TableJoin::RightJoin(_, w) => w,
75 TableJoin::FullJoin(_, w) => w,
76 };
77 if w.len() != 0 {
78 w.push(WhereOperator::And);
79 }
80 w.extend(query_where);
81 self
82 }
83}
84
85#[derive(Debug)]
86pub enum TableJoin {
87 InnerJoin(QueryTable, QueryWheres),
88 LeftJoin(QueryTable, QueryWheres),
89 RightJoin(QueryTable, QueryWheres),
90 FullJoin(QueryTable, QueryWheres),
91}
92
93#[derive(Debug)]
94pub struct QueryTable {
95 alias: Option<String>,
96 name: String,
97 schema: Option<String>,
98 table_join: Vec<TableJoin>,
99}
100
101impl QueryTable {
102 fn get_table_name(&self) -> String {
103 let escaped_table_name = if let Some(schema) = &self.schema {
104 format!("{}{}{}.{}{}{}", TABLE_ESCAPE, schema, TABLE_ESCAPE, TABLE_ESCAPE, self.name, TABLE_ESCAPE)
105 } else {
106 format!("{}{}{}", TABLE_ESCAPE, self.name.clone(), TABLE_ESCAPE)
107 };
108 if let Some(alias) = &self.alias {
109 format!("{} AS {}", escaped_table_name, alias)
110 } else {
111 escaped_table_name
112 }
113 }
114 fn build(&self, i: &mut i8) -> Result<QueryWithParamsLoc, Error> {
115 let mut v: Vec<String> = Vec::new();
116 let mut p: Vec<usize> = Vec::new();
117 v.push(self.get_table_name());
118 for join in &self.table_join {
119 let (op, join_table, qw) = match join {
120 TableJoin::InnerJoin(join_table, qw) => {("INNER JOIN", join_table, qw)},
121 TableJoin::LeftJoin(join_table, qw) => {("LEFT JOIN", join_table, qw)},
122 TableJoin::RightJoin(join_table, qw) => {("RIGHT JOIN", join_table, qw)},
123 TableJoin::FullJoin(join_table, qw) => {("FULL JOIN", join_table, qw)},
124 };
125 v.push(op.to_owned());
126 v.push(join_table.get_table_name());
127 v.push("ON".to_owned());
128 let qwresult = qw.build(i)?;
129 v.push(qwresult.query);
130 p.extend(qwresult.parameters_loc);
131 }
132 Ok(QueryWithParamsLoc {
133 query: v.join(" "),
134 parameters_loc: p,
135 })
136 }
137}
138impl From<&str> for QueryTable {
139 fn from(table: &str) -> Self {
140 QueryTable {
141 alias: None,
142 name: table.to_owned(),
143 schema: None,
144 table_join: Vec::new(),
145 }
146 }
147}
148
149impl From<(&str, &str)> for QueryTable {
150 fn from(nameandalias: (&str, &str)) -> Self {
151 QueryTable {
152 alias: Some(nameandalias.1.to_owned()),
153 name: nameandalias.0.to_owned(),
154 schema: None,
155 table_join: Vec::new(),
156 }
157 }
158}
159
160impl From<(&str, &str, &str)> for QueryTable {
161 fn from(schemaxnamexalias: (&str, &str, &str)) -> Self {
162 QueryTable {
163 alias: Some(schemaxnamexalias.2.to_owned()),
164 name: schemaxnamexalias.1.to_owned(),
165 schema: Some(schemaxnamexalias.0.to_owned()),
166 table_join: Vec::new(),
167 }
168 }
169}
170
171#[cfg(test)]
172mod tests {
173 use super::*;
174 #[test]
175 fn test_table_1() {
176 let table: QueryTable = QueryTable {
177 alias: Some("u".to_owned()),
178 name: "user".to_owned(),
179 schema: Some("public".to_owned()),
180 table_join: Vec::new(),
181 };
182
183 assert_eq!(table.build(&mut 0).unwrap().query, "\"public\".\"user\" AS u");
184 }
185
186 #[test]
187 fn test_table_2() {
188 let table: QueryTable = "user".into();
189 assert_eq!(table.build(&mut 0).unwrap().query, "\"user\"");
190 }
191
192 #[test]
193 fn test_table_3() {
194 let table: QueryTable = ("user", "u").into();
195 assert_eq!(table.build(&mut 0).unwrap().query, "\"user\" AS u");
196 }
197}