use crate::{
error::Result,
manager::{binded::Binded, PostArchiverConnection},
query::FromQuery,
PlatformId, PostId, Tag, TagId,
};
#[derive(Debug, Clone, Default)]
pub struct UpdateTag {
pub name: Option<String>,
pub platform: Option<Option<PlatformId>>,
}
impl UpdateTag {
pub fn name(mut self, name: String) -> Self {
self.name = Some(name);
self
}
pub fn platform(mut self, platform: Option<PlatformId>) -> Self {
self.platform = Some(platform);
self
}
}
pub trait FindTag {
fn name(&self) -> &str;
fn platform(&self) -> Option<PlatformId> {
None
}
}
impl FindTag for &str {
fn name(&self) -> &str {
self
}
}
impl FindTag for (&str, PlatformId) {
fn name(&self) -> &str {
self.0
}
fn platform(&self) -> Option<PlatformId> {
Some(self.1)
}
}
impl FindTag for (&str, Option<PlatformId>) {
fn name(&self) -> &str {
self.0
}
fn platform(&self) -> Option<PlatformId> {
self.1
}
}
impl<'a, C: PostArchiverConnection> Binded<'a, TagId, C> {
pub fn value(&self) -> Result<Tag> {
let mut stmt = self
.conn()
.prepare_cached("SELECT * FROM tags WHERE id = ?")?;
Ok(stmt.query_row([self.id()], Tag::from_row)?)
}
pub fn delete(self) -> Result<()> {
let mut stmt = self
.conn()
.prepare_cached("DELETE FROM tags WHERE id = ?")?;
stmt.execute([self.id()])?;
Ok(())
}
pub fn update(&self, update: UpdateTag) -> Result<()> {
use rusqlite::types::ToSql;
let mut sets: Vec<&str> = Vec::new();
let mut params: Vec<&dyn ToSql> = Vec::new();
macro_rules! push {
($field:expr, $col:expr) => {
if let Some(ref v) = $field {
sets.push($col);
params.push(v);
}
};
}
push!(update.name, "name = ?");
push!(update.platform, "platform = ?");
if sets.is_empty() {
return Ok(());
}
let id = self.id();
params.push(&id);
let sql = format!("UPDATE tags SET {} WHERE id = ?", sets.join(", "));
self.conn().execute(&sql, params.as_slice())?;
Ok(())
}
}
impl<'a, C: PostArchiverConnection> Binded<'a, TagId, C> {
pub fn list_posts(&self) -> Result<Vec<PostId>> {
let mut stmt = self
.conn()
.prepare_cached("SELECT post FROM post_tags WHERE tag = ?")?;
let rows = stmt.query_map([self.id()], |row| row.get(0))?;
rows.collect::<std::result::Result<_, _>>()
.map_err(Into::into)
}
}