From 20cfe717065fa53953e9799036a9972880fec801 Mon Sep 17 00:00:00 2001 From: Joris Date: Sun, 6 Feb 2022 19:30:53 +0100 Subject: Replace a card whenever the front or the back changed --- src/db/db.rs | 25 ++++++++++++++++--------- src/db/sql/2-primary-key-question-responses.sql | 20 ++++++++++++++++++++ 2 files changed, 36 insertions(+), 9 deletions(-) create mode 100644 src/db/sql/2-primary-key-question-responses.sql (limited to 'src/db') diff --git a/src/db/db.rs b/src/db/db.rs index 86614ec..843d142 100644 --- a/src/db/db.rs +++ b/src/db/db.rs @@ -1,5 +1,5 @@ use crate::{ - model::{card::Card, deck::Entry}, + model::{card::Card, entry::Entry}, space_repetition, util::serialization, }; @@ -11,14 +11,21 @@ use std::time::SystemTime; pub fn init(database: String) -> Result { let mut conn = Connection::open(database)?; - let migrations = Migrations::new(vec![M::up(include_str!("sql/1-init.sql"))]); + let migrations = Migrations::new(vec![ + M::up(include_str!("sql/1-init.sql")), + M::up(include_str!("sql/2-primary-key-question-responses.sql")), + ]); migrations.to_latest(&mut conn)?; Ok(conn) } -pub fn add_missing_deck_entries(conn: &Connection, entries: Vec) -> Result<()> { +/// Synchronize the DB with the deck: +/// +/// - insert new cards, +/// - keep existing cards, +/// - hide unused cards (keep state in case the card is added back afterward). +pub fn synchronize(conn: &Connection, entries: Vec) -> Result<()> { let now = get_current_time()?; - let ready = now; let state = serde_json::to_string(&space_repetition::init())?; let mut rng = rand::thread_rng(); @@ -28,11 +35,11 @@ pub fn add_missing_deck_entries(conn: &Connection, entries: Vec) -> Resul let concat_2 = serialization::words_to_line(&entry.part_2); for w in entry.part_1.iter() { - insert(&conn, &mut rng, now, ready, &w, &concat_2, &state)?; + insert(&conn, &mut rng, now, &w, &concat_2, &state)?; } for w in entry.part_2.iter() { - insert(&conn, &mut rng, now, ready, &w, &concat_1, &state)?; + insert(&conn, &mut rng, now, &w, &concat_1, &state)?; } } @@ -45,11 +52,11 @@ fn insert( conn: &Connection, rng: &mut ThreadRng, now: u64, - ready: u64, question: &String, responses: &String, state: &String, ) -> Result<()> { + println!("insert {} : {}", question, responses); // Subtract a random amount of time so that cards are not initially given in the same order as // in the deck let ready_sub: u64 = rng.gen_range(0..100); @@ -58,9 +65,9 @@ fn insert( " INSERT INTO cards (question, responses, state, created, deck_read, ready) VALUES (?, ?, ?, ?, ?, ?) - ON CONFLICT (question) DO UPDATE SET deck_read = ?, deleted = null + ON CONFLICT (question, responses) DO UPDATE SET deck_read = ?, deleted = null ", - params![question, responses, state, now, now, ready - ready_sub, now], + params![question, responses, state, now, now, now - ready_sub, now], )?; Ok(()) diff --git a/src/db/sql/2-primary-key-question-responses.sql b/src/db/sql/2-primary-key-question-responses.sql new file mode 100644 index 0000000..cb7df21 --- /dev/null +++ b/src/db/sql/2-primary-key-question-responses.sql @@ -0,0 +1,20 @@ +/* Allows to use ON CONFLICT on (question, responses) when inserting a card. */ + +CREATE TABLE IF NOT EXISTS cards_copy ( + question VARCHAR NOT NULL, + responses VARCHAR NOT NULL, + state VARCHAR NOT NULL, + created TIMESTAMP NOT NULL, + updated TIMESTAMP NULL, + deleted TIMESTAMP NULL, + deck_read TIMESTAMP NOT NULL, + ready TIMESTAMP NOT NULL, + PRIMARY KEY (question, responses) +); + +INSERT INTO cards_copy (question, responses, state, created, updated, deleted, deck_read, ready) + SELECT question, responses, state, created, updated, deleted, deck_read, ready FROM cards; + +DROP TABLE cards; + +ALTER TABLE cards_copy RENAME TO cards; -- cgit v1.2.3