1use rusqlite::params;
4
5use super::{epoch_secs, Store};
6use crate::error::{Result, StoreError};
7use crate::types::Mark;
8
9impl Store {
10 #[allow(clippy::too_many_arguments)]
11 pub fn create_mark(
12 &mut self,
13 id: &str,
14 session_id: &str,
15 page_id: &str,
16 name: &str,
17 dom_path: &str,
18 role: Option<&str>,
19 content_excerpt: Option<&str>,
20 ) -> Result<Mark> {
21 let now = epoch_secs();
22 self.conn()
23 .execute(
24 "INSERT INTO marks(id, session_id, page_id, name, dom_path,
25 role, content_excerpt, created_at)
26 VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8)",
27 params![
28 id,
29 session_id,
30 page_id,
31 name,
32 dom_path,
33 role,
34 content_excerpt,
35 now
36 ],
37 )
38 .map_err(|e| match e {
39 rusqlite::Error::SqliteFailure(err, _)
40 if err.code == rusqlite::ErrorCode::ConstraintViolation =>
41 {
42 StoreError::Conflict("mark name already in session")
43 }
44 other => StoreError::Sqlite(other),
45 })?;
46 Ok(Mark {
47 id: id.to_string(),
48 session_id: session_id.to_string(),
49 page_id: page_id.to_string(),
50 name: name.to_string(),
51 dom_path: dom_path.to_string(),
52 role: role.map(str::to_string),
53 content_excerpt: content_excerpt.map(str::to_string),
54 created_at: now,
55 })
56 }
57
58 pub fn get_mark(&self, session_id: &str, name: &str) -> Result<Option<Mark>> {
59 let mut stmt = self
60 .conn()
61 .prepare("SELECT * FROM marks WHERE session_id=?1 AND name=?2")?;
62 let mut rows = stmt.query([session_id, name])?;
63 if let Some(row) = rows.next()? {
64 Ok(Some(Mark::from_row(row)?))
65 } else {
66 Ok(None)
67 }
68 }
69
70 pub fn list_marks(&self, session_id: &str) -> Result<Vec<Mark>> {
71 let mut stmt = self
72 .conn()
73 .prepare("SELECT * FROM marks WHERE session_id=?1 ORDER BY created_at ASC")?;
74 let rows = stmt.query_map([session_id], Mark::from_row)?;
75 Ok(rows.collect::<rusqlite::Result<Vec<_>>>()?)
76 }
77
78 pub fn delete_mark(&mut self, session_id: &str, name: &str) -> Result<()> {
79 let n = self.conn().execute(
80 "DELETE FROM marks WHERE session_id=?1 AND name=?2",
81 params![session_id, name],
82 )?;
83 if n == 0 {
84 return Err(StoreError::NotFound {
85 kind: "mark",
86 id: format!("{session_id}/{name}"),
87 });
88 }
89 Ok(())
90 }
91}