add series support

This commit is contained in:
Sebastian Hugentobler 2024-05-06 16:25:15 +02:00
parent 6a79f0c1ed
commit a91fe9a0bb
Signed by: shu
GPG key ID: BB32CF3CA052C2F0
11 changed files with 183 additions and 43 deletions

View file

@ -70,7 +70,7 @@ impl Calibre {
&self,
limit: u64,
cursor: Option<&str>,
sort_order: SortOrder,
sort_order: &SortOrder,
) -> Result<Vec<Series>, DataStoreError> {
let conn = self.pool.get()?;
Series::multiple(&conn, limit, cursor, sort_order)
@ -81,6 +81,11 @@ impl Calibre {
Series::book_series(&conn, id)
}
pub fn series_books(&self, id: u64) -> Result<Vec<Book>, DataStoreError> {
let conn = self.pool.get()?;
Book::series_books(&conn, id)
}
pub fn has_previous_authors(&self, author_sort: &str) -> Result<bool, DataStoreError> {
let conn = self.pool.get()?;
Author::has_previous_authors(&conn, author_sort)
@ -101,10 +106,25 @@ impl Calibre {
Book::has_more_books(&conn, book_sort)
}
pub fn has_previous_series(&self, series_sort: &str) -> Result<bool, DataStoreError> {
let conn = self.pool.get()?;
Series::has_previous_series(&conn, series_sort)
}
pub fn has_more_series(&self, series_sort: &str) -> Result<bool, DataStoreError> {
let conn = self.pool.get()?;
Series::has_more_series(&conn, series_sort)
}
pub fn scalar_author(&self, id: u64) -> Result<Author, DataStoreError> {
let conn = self.pool.get()?;
Author::scalar_author(&conn, id)
}
pub fn scalar_series(&self, id: u64) -> Result<Series, DataStoreError> {
let conn = self.pool.get()?;
Series::scalar_series(&conn, id)
}
}
#[cfg(test)]

View file

@ -57,20 +57,10 @@ impl Author {
conn: &Connection,
sort_name: &str,
) -> Result<bool, DataStoreError> {
let mut stmt = conn
.prepare("SELECT Count(1) FROM authors WHERE sort < (:sort_name) ORDER BY sort DESC")?;
let params = named_params! { ":sort_name": sort_name };
let count: u64 = stmt.query_row(params, |x| x.get(0))?;
Ok(count > 0)
Pagination::has_prev_or_more(conn, "authors", sort_name, &SortOrder::DESC)
}
pub fn has_more_authors(conn: &Connection, sort_name: &str) -> Result<bool, DataStoreError> {
let mut stmt = conn
.prepare("SELECT Count(1) FROM authors WHERE sort > (:sort_name) ORDER BY sort ASC")?;
let params = named_params! { ":sort_name": sort_name };
let count: u64 = stmt.query_row(params, |x| x.get(0))?;
Ok(count > 0)
Pagination::has_prev_or_more(conn, "authors", sort_name, &SortOrder::ASC)
}
}

View file

@ -57,6 +57,19 @@ impl Book {
)
}
pub fn series_books(conn: &Connection, id: u64) -> Result<Vec<Book>, DataStoreError> {
let mut stmt = conn.prepare(
"SELECT books.id, books.title, books.sort, books.path FROM series \
INNER JOIN books_series_link ON series.id = books_series_link.series \
INNER JOIN books ON books.id = books_series_link.book \
WHERE books_series_link.series = (:id) \
ORDER BY books.series_index",
)?;
let params = named_params! { ":id": id };
let iter = stmt.query_map(params, Self::from_row)?;
Ok(iter.filter_map(Result::ok).collect())
}
pub fn recents(conn: &Connection, limit: u64) -> Result<Vec<Self>, DataStoreError> {
let mut stmt = conn.prepare(
"SELECT id, title, sort, path FROM books ORDER BY timestamp DESC LIMIT (:limit)",
@ -73,20 +86,10 @@ impl Book {
}
pub fn has_previous_books(conn: &Connection, sort_title: &str) -> Result<bool, DataStoreError> {
let mut stmt = conn
.prepare("SELECT Count(1) FROM books WHERE sort < (:sort_title) ORDER BY sort DESC")?;
let params = named_params! { ":sort_title": sort_title};
let count: u64 = stmt.query_row(params, |x| x.get(0))?;
Ok(count > 0)
Pagination::has_prev_or_more(conn, "books", sort_title, &SortOrder::DESC)
}
pub fn has_more_books(conn: &Connection, sort_title: &str) -> Result<bool, DataStoreError> {
let mut stmt = conn
.prepare("SELECT Count(1) FROM books WHERE sort > (:sort_title) ORDER BY sort ASC")?;
let params = named_params! { ":sort_title": sort_title};
let count: u64 = stmt.query_row(params, |x| x.get(0))?;
Ok(count > 0)
Pagination::has_prev_or_more(conn, "books", sort_title, &SortOrder::ASC)
}
}

View file

@ -1,4 +1,4 @@
use rusqlite::{Connection, Row, ToSql};
use rusqlite::{named_params, Connection, Row, ToSql};
use serde::{Deserialize, Serialize};
use super::error::DataStoreError;
@ -31,6 +31,32 @@ impl<'a> Pagination<'a> {
}
}
fn sort_order_to_sql(sort_order: &SortOrder) -> String {
if *sort_order == SortOrder::ASC {
">"
} else {
"<"
}
.to_string()
}
pub fn has_prev_or_more(
conn: &Connection,
table: &str,
sort: &str,
sort_order: &SortOrder,
) -> Result<bool, DataStoreError> {
let comparison = Pagination::sort_order_to_sql(sort_order);
let mut stmt = conn.prepare(&format!(
"SELECT Count(1) FROM {table} WHERE sort {comparison} (:sort) ORDER BY sort {sort_order:?}"
))?;
let params = named_params! { ":sort": sort};
let count: u64 = stmt.query_row(params, |x| x.get(0))?;
Ok(count > 0)
}
pub fn paginate<T, F>(
&self,
conn: &Connection,
@ -42,11 +68,8 @@ impl<'a> Pagination<'a> {
F: FnMut(&Row<'_>) -> Result<T, rusqlite::Error>,
{
let cursor = self.cursor.unwrap_or("");
let comparison = if self.sort_order == SortOrder::ASC {
">"
} else {
"<"
};
let comparison = Pagination::sort_order_to_sql(&self.sort_order);
let where_sql = if statement.ends_with("AND") {
""
} else {

View file

@ -26,17 +26,23 @@ impl Series {
conn: &Connection,
limit: u64,
cursor: Option<&str>,
sort_order: SortOrder,
sort_order: &SortOrder,
) -> Result<Vec<Self>, DataStoreError> {
let pagination = Pagination::new("sort", cursor, limit, sort_order);
let pagination = Pagination::new("sort", cursor, limit, *sort_order);
pagination.paginate(
conn,
"SELECT id, title, sort, path FROM series",
"SELECT id, name, sort FROM series",
&[],
Self::from_row,
)
}
pub fn scalar_series(conn: &Connection, id: u64) -> Result<Self, DataStoreError> {
let mut stmt = conn.prepare("SELECT id, name, sort FROM series WHERE id = (:id)")?;
let params = named_params! { ":id": id };
Ok(stmt.query_row(params, Self::from_row)?)
}
pub fn book_series(
conn: &Connection,
book_id: u64,
@ -61,4 +67,12 @@ impl Series {
Err(e) => Err(DataStoreError::SqliteError(e)),
}
}
pub fn has_previous_series(conn: &Connection, sort_name: &str) -> Result<bool, DataStoreError> {
Pagination::has_prev_or_more(conn, "series", sort_name, &SortOrder::DESC)
}
pub fn has_more_series(conn: &Connection, sort_name: &str) -> Result<bool, DataStoreError> {
Pagination::has_prev_or_more(conn, "series", sort_name, &SortOrder::ASC)
}
}