first commit
This commit is contained in:
58
src/db.rs
58
src/db.rs
@@ -871,6 +871,38 @@ impl Db {
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
/// Subscribers per feed, for the whole catalogue in one query -- the feed list would
|
||||
/// otherwise ask once per feed.
|
||||
pub fn subscriber_counts(&self) -> Result<std::collections::HashMap<String, i64>> {
|
||||
let conn = self.conn.lock().unwrap();
|
||||
let mut stmt =
|
||||
conn.prepare("SELECT feed_id, count(*) FROM subscriptions GROUP BY feed_id")?;
|
||||
let out = stmt
|
||||
.query_map([], |r| Ok((r.get::<_, String>(0)?, r.get::<_, i64>(1)?)))?
|
||||
.collect::<rusqlite::Result<std::collections::HashMap<_, _>>>()?;
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
/// Who else would miss this file: subscribers other than `user_id` who have starred
|
||||
/// the item or have not read it yet. Deleting is deleting their copy too.
|
||||
pub fn others_wanting(&self, enclosure_id: i64, user_id: i64) -> Result<(i64, i64)> {
|
||||
let conn = self.conn.lock().unwrap();
|
||||
let mut stmt = conn.prepare(
|
||||
"SELECT
|
||||
sum(CASE WHEN coalesce(st.flagged, 0) = 1 THEN 1 ELSE 0 END),
|
||||
sum(CASE WHEN coalesce(st.read, 0) = 0 THEN 1 ELSE 0 END)
|
||||
FROM enclosures e
|
||||
JOIN subscriptions s ON s.feed_id = e.feed_id AND s.user_id != ?2
|
||||
LEFT JOIN entry_state st
|
||||
ON st.user_id = s.user_id AND st.feed_id = e.feed_id AND st.guid = e.guid
|
||||
WHERE e.id = ?1",
|
||||
)?;
|
||||
let (starred, unread) = stmt.query_row(params![enclosure_id, user_id], |r| {
|
||||
Ok((r.get::<_, Option<i64>>(0)?.unwrap_or(0), r.get::<_, Option<i64>>(1)?.unwrap_or(0)))
|
||||
})?;
|
||||
Ok((starred, unread))
|
||||
}
|
||||
|
||||
pub fn subscribe(&self, user_id: i64, feed_id: &str) -> Result<()> {
|
||||
let conn = self.conn.lock().unwrap();
|
||||
conn.execute(
|
||||
@@ -1274,6 +1306,32 @@ pub fn now() -> i64 {
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn deleting_a_shared_file_asks_about_everyone_else() {
|
||||
let db = Db::memory().unwrap();
|
||||
db.exec_for_test(
|
||||
"INSERT INTO users (id, name, is_admin, created) VALUES (1,'ray',1,0),(2,'sam',0,0),(3,'kit',0,0);
|
||||
INSERT INTO subscriptions (user_id, feed_id, created) VALUES (1,'f',0),(2,'f',0),(3,'f',0);
|
||||
INSERT INTO entries (feed_id, guid, first_seen) VALUES ('f','a',0);
|
||||
INSERT INTO enclosures (id, feed_id, guid, url, path, state) VALUES
|
||||
(1,'f','a','u1','/tmp/a','done');",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// Nobody has touched it: both others still have it unplayed.
|
||||
assert_eq!(db.others_wanting(1, 1).unwrap(), (0, 2));
|
||||
|
||||
// Sam reads it, Kit stars it.
|
||||
db.set_entry_flag(2, "f", "a", EntryFlag::Read, true).unwrap();
|
||||
db.set_entry_flag(3, "f", "a", EntryFlag::Flagged, true).unwrap();
|
||||
assert_eq!(db.others_wanting(1, 1).unwrap(), (1, 1), "one starred it, one has not played it");
|
||||
|
||||
// Asking as Kit, only Ray and Sam count -- and Kit's own star is not a reason to
|
||||
// warn Kit.
|
||||
db.set_entry_flag(1, "f", "a", EntryFlag::Read, true).unwrap();
|
||||
assert_eq!(db.others_wanting(1, 3).unwrap(), (0, 0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn read_state_belongs_to_one_person() {
|
||||
let db = Db::memory().unwrap();
|
||||
|
||||
Reference in New Issue
Block a user