From 1565fef001d60219ad290f41eec3dc80ed246512 Mon Sep 17 00:00:00 2001 From: "Elf M. Sternberg" Date: Wed, 30 Sep 2020 08:53:45 -0700 Subject: [PATCH] REFACTOR: Dry'ing out the insert_new_note feature. Since both `insert_page` and `insert_note` need to insert a note, having that code twice in the same block was annoying, especially since discovering that my oh-so-clever use of `include_str!` precludes me from using the `query!` macros, which want the strings included *before* doing analysis. All that wrestling with the Transaction type turned out to be much simpler when I was able to just devolve it into an Executor. --- server/nm-store/src/lib.rs | 44 ++++++++++---------- server/nm-store/src/store.rs | 80 +++++++++++++++++++----------------- 2 files changed, 65 insertions(+), 59 deletions(-) diff --git a/server/nm-store/src/lib.rs b/server/nm-store/src/lib.rs index b1c4092..3ce99d3 100644 --- a/server/nm-store/src/lib.rs +++ b/server/nm-store/src/lib.rs @@ -12,9 +12,9 @@ mod tests { async fn fresh_inmemory_database() -> NoteStore { let storagepool = NoteStore::new("sqlite://:memory:").await; - assert!(storagepool.is_ok(), "{:?}", storagepool); + assert!(storagepool.is_ok(), "{:?}", storagepool); let storagepool = storagepool.unwrap(); - let reset = storagepool.reset_database().await; + let reset = storagepool.reset_database().await; assert!(reset.is_ok(), "{:?}", reset); storagepool } @@ -45,29 +45,29 @@ mod tests { #[tokio::test(threaded_scheduler)] async fn can_save_a_note() { - let storagepool = fresh_inmemory_database().await; - let note_id = storagepool.insert_note("noteid", "notecontent", "note").await; - assert!(note_id.is_ok(), "{:?}", note_id); - let note_id = note_id.unwrap(); - assert!(note_id > 0); + let storagepool = fresh_inmemory_database().await; + let note_id = storagepool.insert_note("noteid", "notecontent", "note").await; + assert!(note_id.is_ok(), "{:?}", note_id); + let note_id = note_id.unwrap(); + assert!(note_id > 0); - let foundnote = storagepool.fetch_raw_note("noteid").await; - assert!(foundnote.is_ok(), "{:?}", foundnote); - let foundnote = foundnote.unwrap(); - assert_eq!(foundnote.content, "notecontent"); - assert_eq!(foundnote.notetype, "note"); - } + let foundnote = storagepool.fetch_raw_note("noteid").await; + assert!(foundnote.is_ok(), "{:?}", foundnote); + let foundnote = foundnote.unwrap(); + assert_eq!(foundnote.content, "notecontent"); + assert_eq!(foundnote.notetype, "note"); + } #[tokio::test(threaded_scheduler)] async fn can_save_a_page() { - let storagepool = fresh_inmemory_database().await; - let page_id = storagepool.insert_page("pageid", "Test page").await; - assert!(page_id.is_ok(), "{:?}", page_id); + let storagepool = fresh_inmemory_database().await; + let page_id = storagepool.insert_page("pageid", "Test page").await; + assert!(page_id.is_ok(), "{:?}", page_id); - let page = storagepool.fetch_raw_page("pageid").await; - assert!(page.is_ok(), "{:?}", page); - let page = page.unwrap(); - assert_eq!(page.title, "Test page"); - assert!(page.note_id > 0); - } + let page = storagepool.fetch_raw_page("pageid").await; + assert!(page.is_ok(), "{:?}", page); + let page = page.unwrap(); + assert_eq!(page.title, "Test page"); + assert!(page.note_id > 0); + } } diff --git a/server/nm-store/src/store.rs b/server/nm-store/src/store.rs index a298886..cc19d0a 100644 --- a/server/nm-store/src/store.rs +++ b/server/nm-store/src/store.rs @@ -1,9 +1,10 @@ use crate::errors::NoteStoreError; use crate::structs::{RawNote, RawPage}; -use friendly_id; use chrono; +use friendly_id; use sqlx; use sqlx::sqlite::SqlitePool; +use sqlx::{sqlite::Sqlite, Executor}; use std::sync::Arc; /// A handle to our Sqlite database. @@ -13,6 +14,24 @@ pub struct NoteStore(Arc); type NoteResult = core::result::Result; type SqlResult = sqlx::Result; +async fn insert_note<'e, E>(executor: E, id: &str, content: &str, notetype: &str) -> SqlResult +where + E: 'e + Executor<'e, Database = Sqlite>, +{ + let insert_one_note_sql = include_str!("sql/insert_one_note.sql"); + let now = chrono::Utc::now(); + Ok(sqlx::query(insert_one_note_sql) + .bind(&id) + .bind(&content) + .bind(¬etype) + .bind(&now) + .bind(&now) + .bind(&now) + .execute(executor) + .await? + .last_insert_rowid()) +} + impl NoteStore { pub async fn new(url: &str) -> NoteResult { let pool = SqlitePool::connect(url).await?; @@ -37,47 +56,34 @@ impl NoteStore { sqlx::query_as(select_one_note_sql).bind(&id).fetch_one(&*self.0).await } - pub async fn insert_note(&self, id: &str, content: &str, notetype: &str) -> SqlResult { - let insert_one_note_sql = include_str!("sql/insert_one_note.sql"); - let now = chrono::Utc::now(); - Ok(sqlx::query(insert_one_note_sql) - .bind(&id) - .bind(&content) - .bind(¬etype) - .bind(&now).bind(&now).bind(&now) - .execute(&*self.0).await? - .last_insert_rowid()) - } + pub async fn insert_note(&self, id: &str, content: &str, notetype: &str) -> SqlResult { + insert_note(&*self.0, id, content, notetype).await + } - // TODO: We're returning the raw page with the raw note id, note - // the friendly ID. Is there a disconnect there? It's making me - // furiously to think. - pub async fn insert_page(&self, id: &str, title: &str) -> SqlResult { - let insert_one_note_sql = include_str!("sql/insert_one_note.sql"); - let insert_one_page_sql = include_str!("sql/insert_one_page.sql"); + // TODO: We're returning the raw page with the raw note id, note + // the friendly ID. Is there a disconnect there? It's making me + // furiously to think. + pub async fn insert_page(&self, id: &str, title: &str) -> SqlResult { + let insert_one_page_sql = include_str!("sql/insert_one_page.sql"); let new_note_id = friendly_id::create(); - let now = chrono::Utc::now(); + let now = chrono::Utc::now(); let mut tx = self.0.begin().await?; - let note_id = sqlx::query(insert_one_note_sql) - .bind(&new_note_id) - .bind(&"") - .bind(&"page") - .bind(&now).bind(&now).bind(&now) - .execute(&mut tx).await? - .last_insert_rowid(); + let note_id = insert_note(&mut tx, &new_note_id, &"", &"page").await?; - let page_id = sqlx::query(insert_one_page_sql) - .bind(&id) - .bind(&title) - .bind(¬e_id) - .bind(&now).bind(&now).bind(&now) - .execute(&mut tx).await? - .last_insert_rowid(); - - tx.commit().await?; - Ok(page_id) - } + let page_id = sqlx::query(insert_one_page_sql) + .bind(&id) + .bind(&title) + .bind(¬e_id) + .bind(&now) + .bind(&now) + .bind(&now) + .execute(&mut tx) + .await? + .last_insert_rowid(); + tx.commit().await?; + Ok(page_id) + } }