Line data Source code
1 : use rusqlite::{Connection, params};
2 : use serde::{Deserialize, Serialize};
3 :
4 : #[cfg(test)]
5 : mod tests;
6 :
7 : #[derive(Debug, Serialize, PartialEq)]
8 : pub(crate) struct Article {
9 : id: Option<i64>,
10 : title: String,
11 : content: String,
12 : }
13 :
14 : /// Returns the 5 most recently created pages.
15 2 : pub(crate) fn latest_articles(db: &Connection) -> rusqlite::Result<Vec<Article>> {
16 2 : let mut stmt = db.prepare("SELECT page_id, title FROM pages ORDER BY page_id DESC LIMIT 5")?;
17 :
18 5 : let article_iter = stmt.query_map([], |row| {
19 5 : Ok(Article { id: row.get("page_id")?, title: row.get("title")?, content: "".to_string() })
20 5 : })?;
21 2 : let mut articles = Vec::new();
22 7 : for article in article_iter {
23 5 : articles.push(article?);
24 : }
25 2 : Ok(articles)
26 2 : }
27 :
28 : #[derive(Deserialize)]
29 : pub(crate) struct ArticleCreateParams {
30 : title: String,
31 : content: String,
32 : }
33 :
34 4 : pub(crate) fn create_article(
35 4 : db: &Connection,
36 4 : params: ArticleCreateParams, // TODO: Pass by reference
37 4 : user_id: i64,
38 4 : ) -> rusqlite::Result<i64> {
39 4 : let mut stmt = db.prepare("INSERT INTO pages (title) VALUES (?) RETURNING page_id")?;
40 4 : let page_id: i64 = stmt.query_row([params.title], |row| row.get("page_id"))?;
41 3 : let mut stmt =
42 3 : db.prepare("INSERT INTO revisions (page_id, content, user_id) VALUES (?, ?, ?)")?;
43 3 : let _ = stmt.execute(params![page_id, params.content, user_id])?;
44 3 : Ok(page_id)
45 4 : }
46 :
47 : #[derive(Deserialize)]
48 : pub(crate) struct ArticleUpdateParams {
49 : pub page_id: i64,
50 : title: String,
51 : content: String,
52 : }
53 :
54 1 : pub(crate) fn update_article(
55 1 : db: &Connection,
56 1 : params: &ArticleUpdateParams,
57 1 : user_id: i64,
58 1 : ) -> rusqlite::Result<()> {
59 1 : let mut stmt = db.prepare("UPDATE pages SET title = ? WHERE page_id = ?")?;
60 1 : let _ = stmt.execute(params![params.title, params.page_id])?;
61 1 : let mut stmt =
62 1 : db.prepare("INSERT INTO revisions (page_id, content, user_id) VALUES (?, ?, ?)")?;
63 1 : stmt.execute(params![params.page_id, params.content, user_id])?;
64 1 : Ok(())
65 1 : }
66 :
67 : /// Returns the `article` with the `id`.
68 4 : pub(crate) fn find_by_id(db: &Connection, id: i64) -> rusqlite::Result<Article> {
69 4 : let mut stmt = db.prepare(
70 4 : "SELECT p.page_id, p.title, r.content
71 4 : FROM pages p NATURAL JOIN revisions r
72 4 : WHERE p.page_id = ?
73 4 : ORDER BY r.rev_id DESC
74 4 : LIMIT 1",
75 0 : )?;
76 4 : let article: Article = stmt.query_row([id], |row| {
77 : Ok(Article {
78 2 : id: row.get("page_id")?,
79 2 : title: row.get("title")?,
80 2 : content: row.get("content")?,
81 : })
82 2 : })?;
83 2 : Ok(article)
84 4 : }
|