use std::{fmt::Display, time::Duration};
use rusqlite::{params, types::FromSql};
use crate::{
Database, Res, Table,
insert::Insert,
select::{Select, SelectBy},
upsert::Upsert,
};
#[cfg(all(feature = "json", feature = "serde"))]
use serde_json::Value as JsonValue;
#[cfg(all(feature = "json", feature = "serde"))]
use serde_json::to_string as to_json_string;
pub struct SettingsTable;
impl SettingsTable {
pub fn insert_tuple<T: Insert<SettingsTable>>(database: &Database, item: T) -> Res<()> {
database.insert(item)
}
pub fn upsert_tuple<T: Upsert<SettingsTable>>(database: &Database, item: T) -> Res<()> {
database.upsert(item)
}
pub fn get<T: FromSql>(database: &Database, key: &str) -> Res<Option<T>> {
let mut stmt = database.prepare_reader("SELECT key, value FROM settings WHERE key=?1")?;
let rows: Vec<T> = stmt
.query_map(params![key], |row| {
let val: T = row.get(2)?;
Ok(val)
})?
.flatten()
.collect();
if rows.len() == 1 {
let r = rows.into_iter().nth(0);
Ok(r)
} else {
Ok(None)
}
}
}
impl Table for SettingsTable {
const TBL_NAME: &str = "settings";
const CREATE_QUERY: &str = "CREATE TABLE settings (key, value ANY)";
}
impl<S: Display> Insert<SettingsTable> for (S, String) {
fn insert(database: &crate::Database, item: (S, String)) -> crate::Res<()> {
let mut stmt = Self::stmt(database)?;
stmt.execute(params![item.0.to_string(), item.1])?;
Ok(())
}
fn stmt(database: &crate::Database) -> crate::Res<rusqlite::Statement<'_>> {
database.prepare_writer("INSERT INTO settings (key, value) VALUE (?1, ?2)")
}
}
impl<S: Display> Insert<SettingsTable> for (S, u64) {
fn insert(database: &crate::Database, item: (S, u64)) -> crate::Res<()> {
let mut stmt = Self::stmt(database)?;
stmt.execute(params![item.0.to_string(), item.1])?;
Ok(())
}
fn stmt(database: &crate::Database) -> crate::Res<rusqlite::Statement<'_>> {
database.prepare_writer("INSERT INTO settings (key, value) VALUE (?1, ?2)")
}
}
impl<S: Display> Insert<SettingsTable> for (S, Duration) {
fn insert(database: &crate::Database, item: (S, Duration)) -> crate::Res<()> {
let mut stmt = Self::stmt(database)?;
stmt.execute(params![item.0.to_string(), item.1.as_secs()])?;
Ok(())
}
fn stmt(database: &crate::Database) -> crate::Res<rusqlite::Statement<'_>> {
database.prepare_writer("INSERT INTO settings (key, value) VALUE (?1, ?2)")
}
}
impl<S: Display> Insert<SettingsTable> for (S, rusqlite::types::Value) {
fn insert(database: &crate::Database, item: (S, rusqlite::types::Value)) -> crate::Res<()> {
let mut stmt = Self::stmt(database)?;
stmt.execute(params![item.0.to_string(), item.1])?;
Ok(())
}
fn stmt(database: &crate::Database) -> crate::Res<rusqlite::Statement<'_>> {
database.prepare_writer("INSERT INTO settings (key, value) VALUE (?1, ?2)")
}
}
#[cfg(all(feature = "serde", feature = "json"))]
impl<S: Display> Insert<SettingsTable> for (S, JsonValue) {
fn insert(database: &crate::Database, item: (S, JsonValue)) -> crate::Res<()> {
let mut stmt = Self::stmt(database)?;
let json = to_json_string(&item.1).map_err(|e| Errors::Custom(e.to_string()))?;
stmt.execute(params![item.0.to_string(), json])?;
Ok(())
}
fn stmt(database: &crate::Database) -> crate::Res<rusqlite::Statement> {
database.prepare_writer("INSERT INTO settings (key, value) VALUE (?1, ?2)")
}
}
impl Select<(String, rusqlite::types::Value)> for SettingsTable {
const SELECT: &str = "";
fn func(row: &rusqlite::Row) -> Result<(String, rusqlite::types::Value), rusqlite::Error> {
let key = row.get(0)?;
let value = row.get(1)?;
Ok((key, value))
}
}
impl SelectBy<rusqlite::types::Value, String> for SettingsTable {
const SELECT_BY: &str = "SELECT value FROM settings WHERE key=?1";
fn func(row: &rusqlite::Row) -> Result<rusqlite::types::Value, rusqlite::Error> {
let value = row.get(0)?;
Ok(value)
}
}
impl<S: Display> Upsert<SettingsTable> for (S, String) {
fn upsert(database: &crate::Database, item: (S, String)) -> crate::Res<()> {
let mut stmt = Self::stmt(database)?;
stmt.execute(params![item.0.to_string(), item.1])?;
Ok(())
}
fn upstmt(database: &crate::Database) -> crate::Res<rusqlite::Statement<'_>> {
database.prepare_writer("INSERT INTO settings (key, value) VALUE (?1, ?2) ON CONFLICT (key) DO UPDATE SET value = excluded.value WHERE key = excluded.key")
}
}
impl<S: Display> Upsert<SettingsTable> for (S, u64) {
fn upsert(database: &crate::Database, item: (S, u64)) -> crate::Res<()> {
let mut stmt = Self::stmt(database)?;
stmt.execute(params![item.0.to_string(), item.1])?;
Ok(())
}
fn upstmt(database: &crate::Database) -> crate::Res<rusqlite::Statement<'_>> {
database.prepare_writer("INSERT INTO settings (key, value) VALUE (?1, ?2) ON CONFLICT (key) DO UPDATE SET value = excluded.value WHERE key = excluded.key")
}
}
impl<S: Display> Upsert<SettingsTable> for (S, Duration) {
fn upsert(database: &crate::Database, item: (S, Duration)) -> crate::Res<()> {
let mut stmt = Self::stmt(database)?;
stmt.execute(params![item.0.to_string(), item.1.as_secs()])?;
Ok(())
}
fn upstmt(database: &crate::Database) -> crate::Res<rusqlite::Statement<'_>> {
database.prepare_writer("INSERT INTO settings (key, value) VALUE (?1, ?2) ON CONFLICT (key) DO UPDATE SET value = excluded.value WHERE key = excluded.key")
}
}
impl<S: Display> Upsert<SettingsTable> for (S, rusqlite::types::Value) {
fn upsert(database: &crate::Database, item: (S, rusqlite::types::Value)) -> crate::Res<()> {
let mut stmt = Self::stmt(database)?;
stmt.execute(params![item.0.to_string(), item.1])?;
Ok(())
}
fn upstmt(database: &crate::Database) -> crate::Res<rusqlite::Statement<'_>> {
database.prepare_writer("INSERT INTO settings (key, value) VALUE (?1, ?2) ON CONFLICT (key) DO UPDATE SET value = excluded.value WHERE key = excluded.key")
}
}
#[cfg(all(feature = "serde", feature = "json"))]
impl<S: Display> Upsert<SettingsTable> for (S, JsonValue) {
fn upsert(database: &crate::Database, item: (S, JsonValue)) -> crate::Res<()> {
let mut stmt = Self::stmt(database)?;
let json = to_json_string(&item.1).map_err(|e| Errors::Custom(e.to_string()))?;
stmt.execute(params![item.0.to_string(), json])?;
Ok(())
}
fn upstmt(database: &crate::Database) -> crate::Res<rusqlite::Statement> {
database.prepare_writer("INSERT INTO settings (key, value) VALUE (?1, ?2) ON CONFLICT (key) DO UPDATE SET value = excluded.value WHERE key = excluded.key")
}
}