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