1use std::{path::Path};
2use std::fs::create_dir_all;
3use rusqlite::{Connection, Result};
4
5#[macro_export]
6macro_rules! crate_version {
7 () => {
8 env!("CARGO_PKG_VERSION")
9 };
10}
11
12fn get_conn() -> Result<Connection> {
13 let dir = &shellexpand::tilde("~/.dbdir").into_owned();
14 create_dir_all(dir).expect("Create storage dir");
15
16 let path = &shellexpand::tilde("~/.dbdir/bookstore.db").into_owned();
17 let path = Path::new(path);
18 Connection::open(path)
19}
20
21pub fn init_storage() -> Result<()> {
22 println!(" at ~/.dbdir/bookstore.db");
23 let conn = get_conn()?;
24 conn.execute(
25 "Create table if not exists book_marks (
26 id integer primary key,
27 tag text not null unique,
28 mark text not null unique
29 )",
30 []
31 )?;
32 Ok(())
33}
34pub fn read_tags() -> Result<Vec<String>> {
35 let conn = get_conn()?;
36 let mut stmt = conn.prepare("SELECT tag from book_marks ;")?;
37 let rows = stmt.query_map([], |row| Ok(row.get(0)))?;
38 let mut tags = Vec::new();
39 for row in rows {
40 tags.push(row.unwrap()?);
41 }
42 Ok(tags)
43}
44
45pub fn read_mark(tag: &str) -> Result<String> {
46 let conn = get_conn()?;
47
48 let mut stmt = conn.prepare(&format!(
49 "SELECT mark from book_marks
50 where tag = '{}';",
51 &tag
52 ))?;
53
54 stmt.query_row([], |row| row.get(0))
55}
56
57pub fn add_mark(tag: &str, mark: &str) -> Result<()> {
58 let conn = get_conn()?;
59
60 conn.execute(
61 "INSERT INTO book_marks (tag, mark) values (?1, ?2)",
62 &[&tag, &mark],
63 )?;
64 Ok(())
65}
66
67pub fn del_mark(tag: &str) -> Result<()> {
68 let conn = get_conn()?;
69
70 conn.execute(
71 "delete from book_marks where tag = ?1 ;",
72 &[&tag],
73 )?;
74
75 Ok(())
76}
77
78pub fn update_mark(tag: &str, newtag: &str) -> Result<()> {
79 let conn = get_conn()?;
80
81 conn.execute(
82 "update book_marks set tag = ?2 where tag = ?1;",
83 &[&tag, &newtag],
84 )?;
85 Ok(())
86}