1use std::fmt::{self, Display, Formatter};
47
48mod mysql;
49mod types;
50
51pub use mysql::MySqlStore;
52
53#[derive(Debug)]
54pub struct Error(ErrorKind);
55
56impl Display for Error {
57 #[inline]
58 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
59 match &self.0 {
60 ErrorKind::Sqlx(err) => write!(f, "{}", err),
61 ErrorKind::Custom(s) => write!(f, "{}", s),
62 }
63 }
64}
65
66impl std::error::Error for Error {}
67
68impl datastore::Error for Error {
69 fn custom<T>(msg: T) -> Self
70 where
71 T: Display,
72 {
73 Self(ErrorKind::Custom(msg.to_string()))
74 }
75}
76
77#[derive(Debug)]
78pub(crate) enum ErrorKind {
79 Sqlx(sqlx::Error),
80 Custom(String),
81}
82
83#[derive(Clone, Debug)]
84struct Query<'a> {
85 table: &'a str,
86 inner: QueryInner,
87}
88
89#[derive(Clone, Debug)]
90enum QueryInner {
91 Create {
92 columns: Vec<String>,
93 values: Vec<String>,
94 },
95 Delete {
96 conditions: Conditions,
97 },
98 Insert {
99 columns: Vec<String>,
100 values: Vec<String>,
101 },
102 Select {
103 columns: Vec<String>,
104 conditions: Conditions,
105 },
106}
107
108impl<'a> Query<'a> {
109 pub fn new(table: &'a str, kind: QueryKind) -> Self {
110 let inner = match kind {
111 QueryKind::Create => QueryInner::Create {
112 columns: Vec::new(),
113 values: Vec::new(),
114 },
115 QueryKind::Delete => QueryInner::Delete {
116 conditions: Conditions::default(),
117 },
118 QueryKind::Insert => QueryInner::Insert {
119 columns: Vec::new(),
120 values: Vec::new(),
121 },
122 QueryKind::Select => QueryInner::Select {
123 columns: Vec::new(),
124 conditions: Conditions::default(),
125 },
126 };
127
128 Self { table, inner }
129 }
130
131 pub fn push(&mut self, key: String, value: String) {
132 match &mut self.inner {
133 QueryInner::Create { columns, values } => {
134 columns.push(key);
135 values.push(value);
136 }
137 QueryInner::Delete { conditions: _ } => {
138 unreachable!()
139 }
140 QueryInner::Insert { columns, values } => {
141 columns.push(key);
142 values.push(value);
143 }
144 QueryInner::Select {
145 columns,
146 conditions: _,
147 } => {
148 columns.push(key);
149 }
150 }
151 }
152
153 pub fn push_condition(&mut self, condition: Condition) {
154 match &mut self.inner {
155 QueryInner::Create {
156 columns: _,
157 values: _,
158 } => unreachable!(),
159 QueryInner::Delete { conditions } => {
160 conditions.push(condition);
161 }
162 QueryInner::Insert {
163 columns: _,
164 values: _,
165 } => {
166 unreachable!()
167 }
168 QueryInner::Select {
169 columns: _,
170 conditions,
171 } => {
172 conditions.push(condition);
173 }
174 }
175 }
176}
177
178impl<'a> Display for Query<'a> {
179 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
180 match &self.inner {
181 QueryInner::Create { columns, values } => write!(
182 f,
183 "CREATE TABLE IF NOT EXISTS {} ({})",
184 self.table,
185 columns
186 .iter()
187 .zip(values)
188 .map(|(column, value)| format!("{} {}", column, value))
189 .collect::<Vec<String>>()
190 .join(",")
191 ),
192 QueryInner::Delete { conditions } => {
193 write!(f, "DELETE FROM {}{}", self.table, conditions)
194 }
195 QueryInner::Insert { columns, values } => write!(
196 f,
197 "INSERT INTO {} ({}) VALUES ({})",
198 self.table,
199 columns.join(","),
200 values.join(",")
201 ),
202 QueryInner::Select {
203 columns,
204 conditions,
205 } => write!(
206 f,
207 "SELECT {} FROM {}{}",
208 columns.join(","),
209 self.table,
210 conditions
211 ),
212 }
213 }
214}
215
216#[derive(Clone, Debug, Default)]
217struct Conditions {
218 conditions: Vec<Condition>,
219}
220
221impl Conditions {
222 pub fn push(&mut self, value: Condition) {
223 self.conditions.push(value);
224 }
225}
226
227impl Display for Conditions {
228 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
229 if self.conditions.is_empty() {
230 return Ok(());
231 }
232
233 write!(f, " WHERE {}", self.conditions[0])?;
234
235 for condition in self.conditions.iter().skip(1) {
236 write!(f, " AND {}", condition)?;
237 }
238
239 Ok(())
240 }
241}
242
243#[derive(Clone, Debug)]
245struct Condition {
246 column: String,
247 value: String,
248 comparator: Comparator,
249}
250
251impl Condition {
252 pub fn new(column: String, value: String, comparator: Comparator) -> Self {
253 Self {
254 column,
255 value,
256 comparator,
257 }
258 }
259}
260
261impl Display for Condition {
262 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
263 write!(f, "{} {} {}", self.column, self.comparator, self.value)
264 }
265}
266
267#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
268enum Comparator {
269 Eq,
270}
271
272impl Display for Comparator {
273 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
274 let string = match self {
275 Self::Eq => "=",
276 };
277
278 write!(f, "{}", string)
279 }
280}
281
282#[derive(Debug)]
283pub(crate) enum QueryKind {
284 Create,
285 Delete,
286 Insert,
287 Select,
288}