1use crate::Config;
2#[cfg(feature = "mysql")]
3use crate::colored::Colorize;
4use crate::sql::{self, AnyPool};
5use serde_json::Value;
6use serde::de::DeserializeOwned;
7
8pub async fn connect(cfg: &Config) -> AnyPool {
9 let db_url = if cfg.db_connection == "mysql" {
10 format!(
11 "mysql://{}:{}@{}:{}/{}",
12 cfg.db_username, cfg.db_password, cfg.db_host, cfg.db_port, cfg.db_database
13 )
14 } else {
15 format!("sqlite:database/{}.sqlite?mode=rwc", cfg.db_database)
16 };
17
18 sql::any::install_default_drivers();
19
20 let db_url_ref: &str = &db_url;
21 match AnyPool::connect(db_url_ref).await {
22 Ok(pool) => pool,
23 Err(e) => {
24 let err_msg = e.to_string();
25 #[cfg(feature = "mysql")]
26 if (err_msg.contains("1049") || err_msg.contains("Unknown database")) && cfg.db_connection == "mysql" {
27 println!("{}", "⚠️ Database tidak ditemukan. Mencoba membuat database baru...".yellow());
28
29 let root_url = format!(
30 "mysql://{}:{}@{}:{}",
31 cfg.db_username, cfg.db_password, cfg.db_host, cfg.db_port
32 );
33
34 if let Ok(pool) = sql::MySqlPool::connect(&root_url).await {
35 let create_query = format!("CREATE DATABASE IF NOT EXISTS `{}`", cfg.db_database);
36 if sql::query(&create_query).execute(&pool).await.is_ok() {
37 println!("✅ Database '{}' berhasil dibuat.", cfg.db_database.green());
38 return AnyPool::connect(&db_url).await.expect("Gagal terhubung setelah membuat database");
39 }
40 }
41 }
42 let _ = err_msg; panic!("Gagal terhubung ke database: {:?}", e);
44 }
45 }
46}
47
48#[derive(Clone)]
53pub enum WhereClause {
54 Simple { column: String, operator: String, value: Value },
55 Raw { sql: String, binds: Vec<Value> },
56}
57
58#[derive(Clone)]
59pub struct OrderClause {
60 column: String,
61 direction: String,
62}
63
64#[derive(Clone)]
65pub struct QueryBuilder<'a> {
66 pool: &'a AnyPool,
67 table: String,
68 wheres: Vec<WhereClause>,
69 orders: Vec<OrderClause>,
70 limit: Option<usize>,
71}
72
73pub struct DB;
74
75impl DB {
76 pub fn table<'a>(pool: &'a AnyPool, name: &str) -> QueryBuilder<'a> {
77 QueryBuilder::new(pool, name)
78 }
79}
80
81impl<'a> QueryBuilder<'a> {
82 pub fn new(pool: &'a AnyPool, table: &str) -> Self {
83 Self {
84 pool,
85 table: table.to_string(),
86 wheres: Vec::new(),
87 orders: Vec::new(),
88 limit: None,
89 }
90 }
91
92 pub fn where_(mut self, column: &str, value: impl serde::Serialize) -> Self {
93 let val = serde_json::to_value(value).unwrap_or(Value::Null);
94 self.wheres.push(WhereClause::Simple {
95 column: column.to_string(),
96 operator: "=".to_string(),
97 value: val,
98 });
99 self
100 }
101
102 pub fn where_op(mut self, column: &str, operator: &str, value: impl serde::Serialize) -> Self {
103 let val = serde_json::to_value(value).unwrap_or(Value::Null);
104 self.wheres.push(WhereClause::Simple {
105 column: column.to_string(),
106 operator: operator.to_string(),
107 value: val,
108 });
109 self
110 }
111
112 pub fn where_raw(mut self, sql: &str, binds: Vec<Value>) -> Self {
113 self.wheres.push(WhereClause::Raw {
114 sql: sql.to_string(),
115 binds,
116 });
117 self
118 }
119
120 pub fn where_in(self, column: &str, values: Vec<impl serde::Serialize>) -> Self {
121 if values.is_empty() {
122 return self.where_raw("1 = 0", vec![]);
123 }
124 let placeholders: Vec<&str> = (0..values.len()).map(|_| "?").collect();
125 let sql = format!("`{}` IN ({})", column, placeholders.join(", "));
126 let binds: Vec<Value> = values.iter()
127 .map(|v| serde_json::to_value(v).unwrap_or(Value::Null))
128 .collect();
129 self.where_raw(&sql, binds)
130 }
131
132 pub fn pool(&self) -> &'a AnyPool {
133 self.pool
134 }
135
136
137 pub fn order_by(mut self, column: &str, direction: &str) -> Self {
138 self.orders.push(OrderClause {
139 column: column.to_string(),
140 direction: direction.to_string(),
141 });
142 self
143 }
144
145 pub fn limit(mut self, limit: usize) -> Self {
146 self.limit = Some(limit);
147 self
148 }
149
150 fn to_select_sql(&self) -> (String, Vec<Value>) {
151 let mut sql = format!("SELECT * FROM `{}`", self.table);
152 let mut binds = Vec::new();
153
154 if !self.wheres.is_empty() {
155 sql.push_str(" WHERE ");
156 let mut parts = Vec::new();
157 for w in &self.wheres {
158 match w {
159 WhereClause::Simple { column, operator, value } => {
160 parts.push(format!("`{}` {} ?", column, operator));
161 binds.push(value.clone());
162 }
163 WhereClause::Raw { sql: raw_sql, binds: raw_binds } => {
164 parts.push(raw_sql.clone());
165 binds.extend(raw_binds.clone());
166 }
167 }
168 }
169 sql.push_str(&parts.join(" AND "));
170 }
171
172 if !self.orders.is_empty() {
173 sql.push_str(" ORDER BY ");
174 let parts: Vec<String> = self.orders.iter()
175 .map(|o| format!("`{}` {}", o.column, o.direction))
176 .collect();
177 sql.push_str(&parts.join(", "));
178 }
179
180 if let Some(limit) = self.limit {
181 sql.push_str(&format!(" LIMIT {}", limit));
182 }
183
184 (sql, binds)
185 }
186
187 pub async fn first<T: DeserializeOwned>(&self) -> Result<Option<T>, sql::Error> {
188 let mut builder = self.clone();
189 builder.limit = Some(1);
190 let (sql, binds) = builder.to_select_sql();
191
192 let mut query = sql::query(&sql);
193 for b in &binds {
194 query = bind_query_json(query, b);
195 }
196
197 let row_opt = query.fetch_optional(self.pool).await?;
198 if let Some(row) = row_opt {
199 let val = row_to_json_value(&row);
200 let parsed = serde_json::from_value::<T>(val)
201 .map_err(|e| sql::Error::Protocol(format!("Deserialization error: {}", e)))?;
202 Ok(Some(parsed))
203 } else {
204 Ok(None)
205 }
206 }
207
208 pub async fn get<T: DeserializeOwned>(&self) -> Result<Vec<T>, sql::Error> {
209 let (sql, binds) = self.to_select_sql();
210
211 let mut query = sql::query(&sql);
212 for b in &binds {
213 query = bind_query_json(query, b);
214 }
215
216 let rows = query.fetch_all(self.pool).await?;
217 let mut result = Vec::new();
218 for row in rows {
219 let val = row_to_json_value(&row);
220 let parsed = serde_json::from_value::<T>(val)
221 .map_err(|e| sql::Error::Protocol(format!("Deserialization error: {}", e)))?;
222 result.push(parsed);
223 }
224 Ok(result)
225 }
226
227 pub async fn count(&self) -> Result<i64, sql::Error> {
228 let mut sql = format!("SELECT COUNT(*) FROM `{}`", self.table);
229 let mut binds = Vec::new();
230
231 if !self.wheres.is_empty() {
232 sql.push_str(" WHERE ");
233 let mut parts = Vec::new();
234 for w in &self.wheres {
235 match w {
236 WhereClause::Simple { column, operator, value } => {
237 parts.push(format!("`{}` {} ?", column, operator));
238 binds.push(value.clone());
239 }
240 WhereClause::Raw { sql: raw_sql, binds: raw_binds } => {
241 parts.push(raw_sql.clone());
242 binds.extend(raw_binds.clone());
243 }
244 }
245 }
246 sql.push_str(&parts.join(" AND "));
247 }
248
249 let mut query = sql::query(&sql);
250 for b in &binds {
251 query = bind_query_json(query, b);
252 }
253
254 let row = query.fetch_one(self.pool).await?;
255 let count_val: i64 = row.try_get(0).unwrap_or(0);
256 Ok(count_val)
257 }
258
259 pub async fn insert(&self, data: Value) -> Result<(), sql::Error> {
260 let obj = data.as_object().ok_or_else(|| {
261 sql::Error::Protocol("Data insert harus berupa JSON object".into())
262 })?;
263
264 let mut columns = Vec::new();
265 let mut placeholders = Vec::new();
266 let mut binds = Vec::new();
267
268 for (col, val) in obj {
269 columns.push(format!("`{}`", col));
270 placeholders.push("?");
271 binds.push(val.clone());
272 }
273
274 let sql = format!(
275 "INSERT INTO `{}` ({}) VALUES ({})",
276 self.table,
277 columns.join(", "),
278 placeholders.join(", ")
279 );
280
281 let mut query = sql::query(&sql);
282 for b in &binds {
283 query = bind_query_json(query, b);
284 }
285
286 query.execute(self.pool).await?;
287 Ok(())
288 }
289
290 pub async fn insert_get_id(&self, data: Value) -> Result<i64, sql::Error> {
291 let obj = data.as_object().ok_or_else(|| {
292 sql::Error::Protocol("Data insert harus berupa JSON object".into())
293 })?;
294
295 let mut columns = Vec::new();
296 let mut placeholders = Vec::new();
297 let mut binds = Vec::new();
298
299 for (col, val) in obj {
300 columns.push(format!("`{}`", col));
301 placeholders.push("?");
302 binds.push(val.clone());
303 }
304
305 let sql = format!(
306 "INSERT INTO `{}` ({}) VALUES ({})",
307 self.table,
308 columns.join(", "),
309 placeholders.join(", ")
310 );
311
312 let mut conn = self.pool.acquire().await?;
313
314 let mut query = sql::query(&sql);
315 for b in &binds {
316 query = bind_query_json(query, b);
317 }
318
319 let result = query.execute(&mut *conn).await?;
320 if let Some(id) = result.last_insert_id() {
321 if id != 0 {
322 return Ok(id);
323 }
324 }
325
326 if let Ok(row) = sql::query("SELECT last_insert_rowid()").fetch_one(&mut *conn).await {
328 let id: i64 = row.try_get(0).unwrap_or(0);
329 if id != 0 {
330 return Ok(id);
331 }
332 }
333
334 if let Ok(row) = sql::query("SELECT LAST_INSERT_ID()").fetch_one(&mut *conn).await {
336 let id: i64 = row.try_get(0).unwrap_or(0);
337 if id != 0 {
338 return Ok(id);
339 }
340 }
341
342 Ok(0)
343 }
344
345 pub async fn update(&self, data: Value) -> Result<u64, sql::Error> {
346 let obj = data.as_object().ok_or_else(|| {
347 sql::Error::Protocol("Data update harus berupa JSON object".into())
348 })?;
349
350 let mut sets = Vec::new();
351 let mut binds = Vec::new();
352
353 for (col, val) in obj {
354 sets.push(format!("`{}` = ?", col));
355 binds.push(val.clone());
356 }
357
358 let mut sql = format!("UPDATE `{}` SET {}", self.table, sets.join(", "));
359
360 if !self.wheres.is_empty() {
361 sql.push_str(" WHERE ");
362 let mut parts = Vec::new();
363 for w in &self.wheres {
364 match w {
365 WhereClause::Simple { column, operator, value } => {
366 parts.push(format!("`{}` {} ?", column, operator));
367 binds.push(value.clone());
368 }
369 WhereClause::Raw { sql: raw_sql, binds: raw_binds } => {
370 parts.push(raw_sql.clone());
371 binds.extend(raw_binds.clone());
372 }
373 }
374 }
375 sql.push_str(&parts.join(" AND "));
376 }
377
378 let mut query = sql::query(&sql);
379 for b in &binds {
380 query = bind_query_json(query, b);
381 }
382
383 let result = query.execute(self.pool).await?;
384 Ok(result.rows_affected())
385 }
386
387 pub async fn delete(&self) -> Result<u64, sql::Error> {
388 let mut sql = format!("DELETE FROM `{}`", self.table);
389 let mut binds = Vec::new();
390
391 if !self.wheres.is_empty() {
392 sql.push_str(" WHERE ");
393 let mut parts = Vec::new();
394 for w in &self.wheres {
395 match w {
396 WhereClause::Simple { column, operator, value } => {
397 parts.push(format!("`{}` {} ?", column, operator));
398 binds.push(value.clone());
399 }
400 WhereClause::Raw { sql: raw_sql, binds: raw_binds } => {
401 parts.push(raw_sql.clone());
402 binds.extend(raw_binds.clone());
403 }
404 }
405 }
406 sql.push_str(&parts.join(" AND "));
407 }
408
409 let mut query = sql::query(&sql);
410 for b in &binds {
411 query = bind_query_json(query, b);
412 }
413
414 let result = query.execute(self.pool).await?;
415 Ok(result.rows_affected())
416 }
417}
418
419fn bind_query_json<'q>(
424 query: sql::query::Query<'q, sql::Any, sql::any::AnyArguments<'q>>,
425 val: &Value,
426) -> sql::query::Query<'q, sql::Any, sql::any::AnyArguments<'q>> {
427 match val {
428 Value::Null => query.bind(None::<String>),
429 Value::Bool(b) => query.bind(*b),
430 Value::Number(n) => {
431 if let Some(i) = n.as_i64() {
432 query.bind(i)
433 } else if let Some(f) = n.as_f64() {
434 query.bind(f)
435 } else {
436 query.bind(0.0f64)
437 }
438 }
439 Value::String(s) => query.bind(s.clone()),
440 _ => query.bind(val.to_string()),
441 }
442}
443
444pub fn row_to_json_value(row: &sql::any::AnyRow) -> Value {
445 let mut map = serde_json::Map::new();
446 for i in 0..row.len() {
447 let col = row.column(i);
448 let name = col.name();
449 let val = get_json_value(row, i);
450 map.insert(name.to_string(), val);
451 }
452 Value::Object(map)
453}
454
455fn get_json_value(row: &sql::any::AnyRow, index: usize) -> Value {
456 let type_name = row.column(index).type_info().name();
457 if type_name == "NULL" {
458 return Value::Null;
459 }
460
461 let type_name_upper = type_name.to_uppercase();
462 if type_name_upper.contains("DATETIME") || type_name_upper.contains("TIMESTAMP") || type_name_upper.contains("DATE") || type_name_upper.contains("TIME") {
463 if let Ok(Some(s)) = row.try_get::<Option<String>, _>(index) {
464 return Value::String(s);
465 }
466 if let Ok(Some(bytes)) = row.try_get::<Option<Vec<u8>>, _>(index) {
467 if let Ok(s) = String::from_utf8(bytes) {
468 return Value::String(s);
469 }
470 }
471 return Value::Null;
473 }
474
475 if let Ok(Some(i)) = row.try_get::<Option<i64>, _>(index) {
479 return Value::Number(serde_json::Number::from(i));
480 }
481
482 if let Ok(Some(f)) = row.try_get::<Option<f64>, _>(index) {
483 if let Some(num) = serde_json::Number::from_f64(f) {
484 return Value::Number(num);
485 }
486 }
487
488 if let Ok(Some(b)) = row.try_get::<Option<bool>, _>(index) {
489 return Value::Bool(b);
490 }
491
492 if let Ok(Some(s)) = row.try_get::<Option<String>, _>(index) {
493 return Value::String(s);
494 }
495
496 if let Ok(Some(bytes)) = row.try_get::<Option<Vec<u8>>, _>(index) {
497 if let Ok(s) = String::from_utf8(bytes) {
498 return Value::String(s);
499 }
500 }
501
502 Value::Null
503}