1use crate::{
28 Aggregate, Database, Error, FilterOperator, PaginatedResult, Pagination, QueryBuilder, Result,
29 SearchFilter, Sort,
30};
31use serde::{de::DeserializeOwned, Serialize};
32use std::collections::HashMap;
33
34#[allow(async_fn_in_trait)]
36pub trait Model: Serialize + DeserializeOwned + Send + Sync + Clone {
37 fn table_name() -> &'static str;
39
40 fn primary_key() -> &'static str {
42 "id"
43 }
44
45 fn get_primary_key(&self) -> Option<i64>;
47
48 fn set_primary_key(&mut self, id: i64);
50
51 fn columns() -> Vec<&'static str>;
53
54 fn migration_sql() -> String;
56
57 fn to_map(&self) -> Result<HashMap<String, crate::Value>>;
59
60 fn from_map(map: HashMap<String, crate::Value>) -> Result<Self>;
62
63 async fn create(&self, db: &Database) -> Result<Self> {
65 let map = self.to_map()?;
66 let columns: Vec<String> = map.keys().cloned().collect();
67 let values: Vec<String> = map.keys().map(|_| "?".to_string()).collect();
68
69 let sql = format!(
70 "INSERT INTO {} ({}) VALUES ({})",
71 Self::table_name(),
72 columns.join(", "),
73 values.join(", ")
74 );
75
76 Self::log_info(&format!("Creating record in table: {}", Self::table_name()));
77 Self::log_debug(&format!("SQL: {sql}"));
78
79 let params: Vec<libsql::Value> = map
80 .values()
81 .map(|v| Self::value_to_libsql_value(v))
82 .collect();
83
84 db.inner.execute(&sql, params).await?;
85 let id = 1i64; let mut result = self.clone();
88 result.set_primary_key(id);
89
90 Self::log_info(&format!("Successfully created record with ID: {id}"));
91 Ok(result)
92 }
93
94 async fn create_or_update(&self, db: &Database) -> Result<Self> {
96 if let Some(id) = self.get_primary_key() {
97 Self::log_info(&format!("Updating existing record with ID: {id}"));
98 match Self::find_by_id(id, db).await? {
100 Some(_) => {
101 self.update(db).await
103 }
104 None => {
105 Self::log_warn(&format!(
107 "Record with ID {id} not found, creating new record"
108 ));
109 self.create(db).await
110 }
111 }
112 } else {
113 Self::log_info("Creating new record (no primary key provided)");
115 self.create(db).await
116 }
117 }
118
119 async fn upsert(&self, unique_columns: &[&str], db: &Database) -> Result<Self> {
121 let map = self.to_map()?;
122
123 let mut where_conditions = Vec::new();
125 let mut where_params = Vec::new();
126
127 for &column in unique_columns {
128 if let Some(value) = map.get(column) {
129 where_conditions.push(format!("{column} = ?"));
130 where_params.push(Self::value_to_libsql_value(value));
131 }
132 }
133
134 if where_conditions.is_empty() {
135 return Err(Error::Validation(
136 "No unique columns provided for upsert".to_string(),
137 ));
138 }
139
140 let where_clause = where_conditions.join(" AND ");
141 let sql = format!(
142 "SELECT {} FROM {} WHERE {}",
143 Self::primary_key(),
144 Self::table_name(),
145 where_clause
146 );
147
148 Self::log_info(&format!(
149 "Checking for existing record in table: {}",
150 Self::table_name()
151 ));
152 Self::log_debug(&format!("SQL: {sql}"));
153
154 let mut rows = db.inner.query(&sql, where_params).await?;
155
156 if let Some(row) = rows.next().await? {
157 if let Some(existing_id) = row.get_value(0).ok().and_then(|v| match v {
159 libsql::Value::Integer(i) => Some(i),
160 _ => None,
161 }) {
162 Self::log_info(&format!(
163 "Found existing record with ID: {existing_id}, updating"
164 ));
165 let mut updated_self = self.clone();
166 updated_self.set_primary_key(existing_id);
167 updated_self.update(db).await
168 } else {
169 Err(Error::Query(
170 "Failed to get primary key from existing record".to_string(),
171 ))
172 }
173 } else {
174 Self::log_info("No existing record found, creating new one");
176 self.create(db).await
177 }
178 }
179
180 async fn bulk_create(models: &[Self], db: &Database) -> Result<Vec<Self>> {
182 if models.is_empty() {
183 return Ok(Vec::new());
184 }
185
186 let mut results = Vec::new();
187 db.inner
189 .execute("BEGIN", vec![libsql::Value::Null; 0])
190 .await?;
191
192 for model in models {
193 let map = model.to_map()?;
194 let columns: Vec<String> = map.keys().cloned().collect();
195 let values: Vec<String> = map.keys().map(|_| "?".to_string()).collect();
196
197 let sql = format!(
198 "INSERT INTO {} ({}) VALUES ({})",
199 Self::table_name(),
200 columns.join(", "),
201 values.join(", ")
202 );
203
204 let params: Vec<libsql::Value> = map
205 .values()
206 .map(|v| Self::value_to_libsql_value(v))
207 .collect();
208
209 db.inner.execute(&sql, params).await?;
210 let id = 1i64; let mut result = model.clone();
213 result.set_primary_key(id);
214 results.push(result);
215 }
216
217 db.inner
218 .execute("COMMIT", vec![libsql::Value::Null; 0])
219 .await?;
220 Ok(results)
221 }
222
223 async fn find_by_id(id: i64, db: &Database) -> Result<Option<Self>> {
225 let sql = format!(
226 "SELECT * FROM {} WHERE {} = ?",
227 Self::table_name(),
228 Self::primary_key()
229 );
230
231 Self::log_debug(&format!("Finding record by ID: {id}"));
232 Self::log_debug(&format!("SQL: {sql}"));
233
234 let mut rows = db
235 .inner
236 .query(&sql, vec![libsql::Value::Integer(id)])
237 .await?;
238
239 if let Some(row) = rows.next().await? {
240 let map = Self::row_to_map(&row)?;
241 Self::log_debug(&format!("Found record with ID: {id}"));
242 Ok(Some(Self::from_map(map)?))
243 } else {
244 Self::log_debug(&format!("No record found with ID: {id}"));
245 Ok(None)
246 }
247 }
248
249 async fn find_one(filter: FilterOperator, db: &Database) -> Result<Option<Self>> {
251 let builder = QueryBuilder::new(Self::table_name())
252 .r#where(filter)
253 .limit(1);
254
255 let results = builder.execute::<Self>(db).await?;
256 Ok(results.into_iter().next())
257 }
258
259 async fn find_all(db: &Database) -> Result<Vec<Self>> {
261 let builder = QueryBuilder::new(Self::table_name());
262 builder.execute::<Self>(db).await
263 }
264
265 async fn find_where(filter: FilterOperator, db: &Database) -> Result<Vec<Self>> {
267 let builder = QueryBuilder::new(Self::table_name()).r#where(filter);
268 builder.execute::<Self>(db).await
269 }
270
271 async fn find_paginated(
273 pagination: &Pagination,
274 db: &Database,
275 ) -> Result<PaginatedResult<Self>> {
276 let builder = QueryBuilder::new(Self::table_name());
277 builder.execute_paginated::<Self>(db, pagination).await
278 }
279
280 async fn find_where_paginated(
282 filter: FilterOperator,
283 pagination: &Pagination,
284 db: &Database,
285 ) -> Result<PaginatedResult<Self>> {
286 let builder = QueryBuilder::new(Self::table_name()).r#where(filter);
287 builder.execute_paginated::<Self>(db, pagination).await
288 }
289
290 async fn search(
292 search_filter: &SearchFilter,
293 pagination: Option<&Pagination>,
294 db: &Database,
295 ) -> Result<PaginatedResult<Self>> {
296 let filter = search_filter.to_filter_operator();
297 let pagination = pagination.unwrap_or(&Pagination::default()).clone();
298
299 Self::find_where_paginated(filter, &pagination, db).await
300 }
301
302 async fn count(db: &Database) -> Result<u64> {
304 let sql = format!("SELECT COUNT(*) FROM {}", Self::table_name());
305 let mut rows = db.inner.query(&sql, vec![libsql::Value::Null; 0]).await?;
306
307 if let Some(row) = rows.next().await? {
308 row.get_value(0)
309 .ok()
310 .and_then(|v| match v {
311 libsql::Value::Integer(i) => Some(i as u64),
312 _ => None,
313 })
314 .ok_or_else(|| Error::Query("Failed to get count".to_string()))
315 } else {
316 Err(Error::Query("No count result".to_string()))
317 }
318 }
319
320 async fn count_where(filter: FilterOperator, db: &Database) -> Result<u64> {
322 let builder = QueryBuilder::new(Self::table_name()).r#where(filter);
323
324 let (sql, params) = builder.build_count()?;
325 let mut rows = db.inner.query(&sql, params).await?;
326
327 if let Some(row) = rows.next().await? {
328 row.get_value(0)
329 .ok()
330 .and_then(|v| match v {
331 libsql::Value::Integer(i) => Some(i as u64),
332 _ => None,
333 })
334 .ok_or_else(|| Error::Query("Failed to get count".to_string()))
335 } else {
336 Err(Error::Query("No count result".to_string()))
337 }
338 }
339
340 async fn update(&self, db: &Database) -> Result<Self> {
342 let id = self.get_primary_key().ok_or_else(|| {
343 Error::Validation("Cannot update record without primary key".to_string())
344 })?;
345
346 let map = self.to_map()?;
347 let set_clauses: Vec<String> = map
348 .keys()
349 .filter(|&k| k != Self::primary_key())
350 .map(|k| format!("{k} = ?"))
351 .collect();
352
353 let sql = format!(
354 "UPDATE {} SET {} WHERE {} = ?",
355 Self::table_name(),
356 set_clauses.join(", "),
357 Self::primary_key()
358 );
359
360 Self::log_info(&format!("Updating record with ID: {id}"));
361 Self::log_debug(&format!("SQL: {sql}"));
362
363 let mut params: Vec<libsql::Value> = map
364 .iter()
365 .filter(|(k, _)| k != &Self::primary_key())
366 .map(|(_, v)| Self::value_to_libsql_value(v))
367 .collect();
368 params.push(libsql::Value::Integer(id));
369
370 db.inner.execute(&sql, params).await?;
371 Self::log_info(&format!("Successfully updated record with ID: {id}"));
372 Ok(self.clone())
373 }
374
375 async fn bulk_update(models: &[Self], db: &Database) -> Result<Vec<Self>> {
377 if models.is_empty() {
378 return Ok(Vec::new());
379 }
380
381 let mut results = Vec::new();
382 db.inner
384 .execute("BEGIN", vec![libsql::Value::Null; 0])
385 .await?;
386
387 for model in models {
388 let result = model.update(db).await?;
389 results.push(result);
390 }
391
392 db.inner
393 .execute("COMMIT", vec![libsql::Value::Null; 0])
394 .await?;
395 Ok(results)
396 }
397
398 async fn delete(&self, db: &Database) -> Result<bool> {
400 let id = self.get_primary_key().ok_or_else(|| {
401 Error::Validation("Cannot delete record without primary key".to_string())
402 })?;
403
404 let sql = format!(
405 "DELETE FROM {} WHERE {} = ?",
406 Self::table_name(),
407 Self::primary_key()
408 );
409
410 Self::log_info(&format!("Deleting record with ID: {id}"));
411 Self::log_debug(&format!("SQL: {sql}"));
412
413 db.inner
414 .execute(&sql, vec![libsql::Value::Integer(id)])
415 .await?;
416 Self::log_info(&format!("Successfully deleted record with ID: {id}"));
417 Ok(true)
418 }
419
420 async fn bulk_delete(ids: &[i64], db: &Database) -> Result<u64> {
422 if ids.is_empty() {
423 return Ok(0);
424 }
425
426 let placeholders: Vec<String> = ids.iter().map(|_| "?".to_string()).collect();
427 let sql = format!(
428 "DELETE FROM {} WHERE {} IN ({})",
429 Self::table_name(),
430 Self::primary_key(),
431 placeholders.join(", ")
432 );
433
434 let params: Vec<libsql::Value> = ids.iter().map(|&id| libsql::Value::Integer(id)).collect();
435 db.inner.execute(&sql, params).await?;
436 Ok(ids.len() as u64)
437 }
438
439 async fn delete_where(filter: FilterOperator, db: &Database) -> Result<u64> {
441 let builder = QueryBuilder::new(Self::table_name()).r#where(filter);
442
443 let (sql, params) = builder.build()?;
444 let delete_sql = sql.replace("SELECT *", "DELETE");
445 db.inner.execute(&delete_sql, params).await?;
446
447 Ok(1)
450 }
451
452 async fn list(
454 sort: Option<Vec<Sort>>,
455 pagination: Option<&Pagination>,
456 db: &Database,
457 ) -> Result<PaginatedResult<Self>> {
458 let mut builder = QueryBuilder::new(Self::table_name());
459
460 if let Some(sorts) = sort {
461 builder = builder.order_by_multiple(sorts);
462 }
463
464 let pagination = pagination.unwrap_or(&Pagination::default()).clone();
465 builder.execute_paginated::<Self>(db, &pagination).await
466 }
467
468 async fn list_where(
470 filter: FilterOperator,
471 sort: Option<Vec<Sort>>,
472 pagination: Option<&Pagination>,
473 db: &Database,
474 ) -> Result<PaginatedResult<Self>> {
475 let mut builder = QueryBuilder::new(Self::table_name()).r#where(filter);
476
477 if let Some(sorts) = sort {
478 builder = builder.order_by_multiple(sorts);
479 }
480
481 let pagination = pagination.unwrap_or(&Pagination::default()).clone();
482 builder.execute_paginated::<Self>(db, &pagination).await
483 }
484
485 async fn query(builder: QueryBuilder, db: &Database) -> Result<Vec<Self>> {
487 builder.execute::<Self>(db).await
488 }
489
490 async fn query_paginated(
492 builder: QueryBuilder,
493 pagination: &Pagination,
494 db: &Database,
495 ) -> Result<PaginatedResult<Self>> {
496 builder.execute_paginated::<Self>(db, pagination).await
497 }
498
499 async fn aggregate(
501 function: Aggregate,
502 column: &str,
503 filter: Option<FilterOperator>,
504 db: &Database,
505 ) -> Result<Option<f64>> {
506 let mut builder =
507 QueryBuilder::new(Self::table_name()).aggregate(function, column, None::<String>);
508
509 if let Some(filter) = filter {
510 builder = builder.r#where(filter);
511 }
512
513 let (sql, params) = builder.build()?;
514 let mut rows = db.inner.query(&sql, params).await?;
515
516 if let Some(row) = rows.next().await? {
517 let value = row
518 .get_value(0)
519 .ok()
520 .and_then(|v| match v {
521 libsql::Value::Integer(i) => Some(i as f64),
522 libsql::Value::Real(f) => Some(f),
523 _ => None,
524 })
525 .ok_or_else(|| Error::Query("Failed to get aggregate value".to_string()))?;
526 Ok(Some(value))
527 } else {
528 Ok(None)
529 }
530 }
531
532 fn row_to_map(row: &libsql::Row) -> Result<HashMap<String, crate::Value>> {
534 let mut map = HashMap::new();
535 for i in 0..row.column_count() {
536 if let Some(column_name) = row.column_name(i) {
537 let value = row.get_value(i).unwrap_or(libsql::Value::Null);
538 map.insert(column_name.to_string(), Self::libsql_value_to_value(&value));
539 }
540 }
541 Ok(map)
542 }
543
544 fn value_to_libsql_value(value: &crate::Value) -> libsql::Value {
546 match value {
547 crate::Value::Null => libsql::Value::Null,
548 crate::Value::Integer(i) => libsql::Value::Integer(*i),
549 crate::Value::Real(f) => libsql::Value::Real(*f),
550 crate::Value::Text(s) => libsql::Value::Text(s.clone()),
551 crate::Value::Blob(b) => libsql::Value::Blob(b.clone()),
552 crate::Value::Boolean(b) => libsql::Value::Integer(if *b { 1 } else { 0 }),
553 }
554 }
555
556 fn libsql_value_to_value(value: &libsql::Value) -> crate::Value {
558 match value {
559 libsql::Value::Null => crate::Value::Null,
560 libsql::Value::Integer(i) => crate::Value::Integer(*i),
561 libsql::Value::Real(f) => crate::Value::Real(*f),
562 libsql::Value::Text(s) => crate::Value::Text(s.clone()),
563 libsql::Value::Blob(b) => crate::Value::Blob(b.clone()),
564 }
565 }
566
567 fn log_info(message: &str) {
569 #[cfg(target_arch = "wasm32")]
570 {
571 web_sys::console::log_1(&format!("[INFO] {}: {}", Self::table_name(), message).into());
572 }
573 #[cfg(not(target_arch = "wasm32"))]
574 {
575 log::info!("[{}] {}", Self::table_name(), message);
576 }
577 }
578
579 fn log_debug(message: &str) {
581 #[cfg(target_arch = "wasm32")]
582 {
583 web_sys::console::log_1(&format!("[DEBUG] {}: {}", Self::table_name(), message).into());
584 }
585 #[cfg(not(target_arch = "wasm32"))]
586 {
587 log::debug!("[{}] {}", Self::table_name(), message);
588 }
589 }
590
591 fn log_warn(message: &str) {
593 #[cfg(target_arch = "wasm32")]
594 {
595 web_sys::console::warn_1(&format!("[WARN] {}: {}", Self::table_name(), message).into());
596 }
597 #[cfg(not(target_arch = "wasm32"))]
598 {
599 log::warn!("[{}] {}", Self::table_name(), message);
600 }
601 }
602
603 fn log_error(message: &str) {
605 #[cfg(target_arch = "wasm32")]
606 {
607 web_sys::console::error_1(
608 &format!("[ERROR] {}: {}", Self::table_name(), message).into(),
609 );
610 }
611 #[cfg(not(target_arch = "wasm32"))]
612 {
613 log::error!("[{}] {}", Self::table_name(), message);
614 }
615 }
616}