Want to contribute? Fork me on Codeberg.org!
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

80 lines
2.2 KiB

use crate::word::Word;
use derive_more::From;
use rusqlite::{params, Connection, Result};
use std::path::PathBuf;
pub struct Database {
conn: Connection,
pub last_word_id: i64,
}
#[derive(From, Debug)]
pub enum DatabaseCreationError {
RusqliteError(rusqlite::Error),
IoError(std::io::Error),
}
#[derive(Default)]
pub enum DatabaseType {
#[default]
InMemory,
OnDisk(String),
}
#[derive(Default)]
pub struct DatabaseSettings {
pub db_type: DatabaseType,
}
impl Database {
pub fn new(settings: DatabaseSettings) -> Result<Self, DatabaseCreationError> {
let conn = match settings.db_type {
DatabaseType::InMemory => Connection::open_in_memory(),
DatabaseType::OnDisk(path) => Connection::open(PathBuf::from(path)),
}?;
conn.execute(
"CREATE TABLE IF NOT EXISTS word (
id INTEGER PRIMARY KEY,
word TEXT,
reading TEXT,
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
)",
params![],
)?;
let last_word_id = match conn
.prepare("SELECT id FROM word ORDER BY id DESC LIMIT 1")?
.query_map(params![], |row| row.get(0))?
.collect::<Result<Vec<i64>>>()?
.first()
{
Some(id) => *id,
None => 0, // first database entry is id 1
};
Ok(Self { conn, last_word_id })
}
pub fn load_words_before(&self, before_id: i64) -> Result<Vec<Word>> {
self.conn
.prepare("SELECT id, word, reading, timestamp FROM word WHERE id < ? ORDER BY id DESC LIMIT 10")?
.query_map(params![before_id], |row| {
Ok(Word {
id: row.get(0)?,
word: row.get(1)?,
reading: row.get(2)?,
timestamp: row.get(3)?,
})
})?
.collect::<Result<Vec<Word>>>()
}
pub fn add_word(&mut self, word: &Word) -> Result<()> {
self.conn.execute(
"INSERT INTO word (word, reading) VALUES (?1, ?2)",
params![word.word, word.reading,],
)?;
self.last_word_id += 1;
Ok(())
}
}