use crate::prelude::*;
use r2d2::PooledConnection;
use r2d2_sqlite::SqliteConnectionManager;
use rusqlite::Row;
pub fn page_clause(offset: Option<i64>, limit: Option<i64>) -> Result<(String, Vec<i64>)> {
if let Some(value) = offset {
if value < 0 {
bail!("offset must not be negative, got {value}");
}
}
if let Some(value) = limit {
if value < 0 {
bail!("limit must not be negative, got {value}");
}
}
Ok(match (offset, limit) {
(None, None) => (String::new(), Vec::new()),
(None, Some(limit)) => (" LIMIT ?".to_string(), vec![limit]),
(Some(offset), None) => (" LIMIT -1 OFFSET ?".to_string(), vec![offset]),
(Some(offset), Some(limit)) => (" LIMIT ? OFFSET ?".to_string(), vec![limit, offset]),
})
}
#[allow(async_fn_in_trait)]
pub trait Repository<T: Clone> {
fn get_connection(&self) -> Result<r2d2::PooledConnection<SqliteConnectionManager>>;
fn map_row(row: &Row) -> Result<T>;
fn create_impl(
&self,
entity: &T,
conn: &PooledConnection<SqliteConnectionManager>,
) -> Result<()>;
fn find_by_id_impl(
&self,
id: &str,
conn: &PooledConnection<SqliteConnectionManager>,
) -> Result<Option<T>>;
fn update_impl(
&self,
entity: &T,
conn: &PooledConnection<SqliteConnectionManager>,
) -> Result<()>;
fn upsert_impl(
&self,
entity: &T,
conn: &PooledConnection<SqliteConnectionManager>,
) -> Result<()>;
fn delete_impl(&self, id: &str, conn: &PooledConnection<SqliteConnectionManager>)
-> Result<()>;
fn list_impl(
&self,
conn: &PooledConnection<SqliteConnectionManager>,
offset: Option<i64>,
limit: Option<i64>,
) -> Result<Vec<T>>;
fn count_impl(&self, conn: &PooledConnection<SqliteConnectionManager>) -> Result<i64>;
async fn create(&self, entity: &T) -> Result<()> {
let conn = self.get_connection()?;
self.create_impl(entity, &conn)
}
async fn find_by_id(&self, id: &str) -> Result<Option<T>> {
let conn = self.get_connection()?;
self.find_by_id_impl(id, &conn)
}
async fn update(&self, entity: &T) -> Result<()> {
let conn = self.get_connection()?;
self.update_impl(entity, &conn)
}
async fn upsert(&self, entity: &T) -> Result<()> {
let conn = self.get_connection()?;
self.upsert_impl(entity, &conn)
}
async fn delete(&self, id: &str) -> Result<()> {
let conn = self.get_connection()?;
self.delete_impl(id, &conn)
}
async fn list(&self, offset: Option<i64>, limit: Option<i64>) -> Result<Vec<T>> {
let conn = self.get_connection()?;
self.list_impl(&conn, offset, limit)
}
async fn count(&self) -> Result<i64> {
let conn = self.get_connection()?;
self.count_impl(&conn)
}
}