refactor: decide to not create separate table for subscriptions
parent
3e79bec974
commit
064365fb4f
|
@ -29,41 +29,32 @@ create table devices (
|
||||||
unique (user_id, device_id)
|
unique (user_id, device_id)
|
||||||
);
|
);
|
||||||
|
|
||||||
create table subscriptions (
|
|
||||||
id integer primary key not null,
|
|
||||||
|
|
||||||
url text unique not null
|
|
||||||
);
|
|
||||||
|
|
||||||
create table device_subscriptions (
|
create table device_subscriptions (
|
||||||
id integer primary key not null,
|
id integer primary key not null,
|
||||||
|
|
||||||
device_id bigint not null
|
device_id bigint not null
|
||||||
references devices (id)
|
references devices (id)
|
||||||
on delete cascade,
|
on delete cascade,
|
||||||
subscription_id bigint not null
|
|
||||||
references subscriptions (id)
|
podcast_url text not null,
|
||||||
on delete cascade
|
|
||||||
|
|
||||||
time_changed bigint not null default 0,
|
time_changed bigint not null default 0,
|
||||||
deleted boolean not null default false,
|
deleted boolean not null default false,
|
||||||
|
|
||||||
unique (device_id, subscription_id)
|
unique (device_id, podcast_url)
|
||||||
);
|
);
|
||||||
|
|
||||||
create table episode_actions (
|
create table episode_actions (
|
||||||
id integer primary key not null,
|
id integer primary key not null,
|
||||||
|
|
||||||
subscription_id bigint not null
|
|
||||||
references subscriptions (id)
|
|
||||||
on delete set null,
|
|
||||||
|
|
||||||
-- Can be null, as the device is not always provided
|
-- Can be null, as the device is not always provided
|
||||||
device_id bigint
|
device_id bigint
|
||||||
references devices (id)
|
references devices (id)
|
||||||
on delete set null,
|
on delete set null,
|
||||||
|
|
||||||
|
podcast_url text not null,
|
||||||
episode_url text not null,
|
episode_url text not null,
|
||||||
|
|
||||||
timestamp bigint,
|
timestamp bigint,
|
||||||
action text not null,
|
action text not null,
|
||||||
started integer,
|
started integer,
|
||||||
|
|
|
@ -5,7 +5,7 @@ mod schema;
|
||||||
pub use models::device::{Device, DeviceType, NewDevice};
|
pub use models::device::{Device, DeviceType, NewDevice};
|
||||||
pub use models::episode_action::{ActionType, EpisodeAction, NewEpisodeAction};
|
pub use models::episode_action::{ActionType, EpisodeAction, NewEpisodeAction};
|
||||||
pub use models::session::Session;
|
pub use models::session::Session;
|
||||||
pub use models::subscription::{NewSubscription, Subscription};
|
pub use models::device_subscription::{NewDeviceSubscription, DeviceSubscription};
|
||||||
pub use models::user::{NewUser, User};
|
pub use models::user::{NewUser, User};
|
||||||
|
|
||||||
pub use repository::SqliteRepository;
|
pub use repository::SqliteRepository;
|
||||||
|
|
|
@ -6,39 +6,39 @@ use serde::{Deserialize, Serialize};
|
||||||
use crate::db::{schema::*, DbPool, DbResult};
|
use crate::db::{schema::*, DbPool, DbResult};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Queryable, Selectable)]
|
#[derive(Serialize, Deserialize, Clone, Queryable, Selectable)]
|
||||||
#[diesel(table_name = subscriptions)]
|
#[diesel(table_name = device_subscriptions)]
|
||||||
#[diesel(check_for_backend(diesel::sqlite::Sqlite))]
|
#[diesel(check_for_backend(diesel::sqlite::Sqlite))]
|
||||||
pub struct Subscription {
|
pub struct DeviceSubscription {
|
||||||
pub id: i64,
|
pub id: i64,
|
||||||
pub device_id: i64,
|
pub device_id: i64,
|
||||||
pub url: String,
|
pub podcast_url: String,
|
||||||
pub time_changed: i64,
|
pub time_changed: i64,
|
||||||
pub deleted: bool,
|
pub deleted: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Insertable)]
|
#[derive(Deserialize, Insertable)]
|
||||||
#[diesel(table_name = subscriptions)]
|
#[diesel(table_name = device_subscriptions)]
|
||||||
#[diesel(check_for_backend(diesel::sqlite::Sqlite))]
|
#[diesel(check_for_backend(diesel::sqlite::Sqlite))]
|
||||||
pub struct NewSubscription {
|
pub struct NewDeviceSubscription {
|
||||||
pub device_id: i64,
|
pub device_id: i64,
|
||||||
pub url: String,
|
pub podcast_url: String,
|
||||||
pub time_changed: i64,
|
pub time_changed: i64,
|
||||||
pub deleted: bool,
|
pub deleted: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Subscription {
|
impl DeviceSubscription {
|
||||||
pub fn for_device(pool: &DbPool, device_id: i64) -> DbResult<Vec<String>> {
|
pub fn for_device(pool: &DbPool, device_id: i64) -> DbResult<Vec<String>> {
|
||||||
Ok(subscriptions::table
|
Ok(device_subscriptions::table
|
||||||
.select(subscriptions::url)
|
.select(device_subscriptions::podcast_url)
|
||||||
.filter(subscriptions::device_id.eq(device_id))
|
.filter(device_subscriptions::device_id.eq(device_id))
|
||||||
.get_results(&mut pool.get()?)?)
|
.get_results(&mut pool.get()?)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn for_user(pool: &DbPool, user_id: i64) -> DbResult<Vec<String>> {
|
pub fn for_user(pool: &DbPool, user_id: i64) -> DbResult<Vec<String>> {
|
||||||
Ok(subscriptions::table
|
Ok(device_subscriptions::table
|
||||||
.inner_join(devices::table)
|
.inner_join(devices::table)
|
||||||
.filter(devices::user_id.eq(user_id))
|
.filter(devices::user_id.eq(user_id))
|
||||||
.select(subscriptions::url)
|
.select(device_subscriptions::podcast_url)
|
||||||
.distinct()
|
.distinct()
|
||||||
.get_results(&mut pool.get()?)?)
|
.get_results(&mut pool.get()?)?)
|
||||||
}
|
}
|
||||||
|
@ -55,9 +55,9 @@ impl Subscription {
|
||||||
// on conflict. Therefore, we instead calculate which URLs should be inserted and which
|
// on conflict. Therefore, we instead calculate which URLs should be inserted and which
|
||||||
// updated, so we avoid conflicts.
|
// updated, so we avoid conflicts.
|
||||||
let urls: HashSet<String> = urls.into_iter().collect();
|
let urls: HashSet<String> = urls.into_iter().collect();
|
||||||
let urls_in_db: HashSet<String> = subscriptions::table
|
let urls_in_db: HashSet<String> = device_subscriptions::table
|
||||||
.select(subscriptions::url)
|
.select(device_subscriptions::podcast_url)
|
||||||
.filter(subscriptions::device_id.eq(device_id))
|
.filter(device_subscriptions::device_id.eq(device_id))
|
||||||
.get_results(&mut pool.get()?)?
|
.get_results(&mut pool.get()?)?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect();
|
.collect();
|
||||||
|
@ -75,41 +75,41 @@ impl Subscription {
|
||||||
|
|
||||||
// Mark the URLs to delete as properly deleted
|
// Mark the URLs to delete as properly deleted
|
||||||
diesel::update(
|
diesel::update(
|
||||||
subscriptions::table.filter(
|
device_subscriptions::table.filter(
|
||||||
subscriptions::device_id
|
device_subscriptions::device_id
|
||||||
.eq(device_id)
|
.eq(device_id)
|
||||||
.and(subscriptions::url.eq_any(urls_to_delete)),
|
.and(device_subscriptions::podcast_url.eq_any(urls_to_delete)),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.set((
|
.set((
|
||||||
subscriptions::deleted.eq(true),
|
device_subscriptions::deleted.eq(true),
|
||||||
subscriptions::time_changed.eq(timestamp),
|
device_subscriptions::time_changed.eq(timestamp),
|
||||||
))
|
))
|
||||||
.execute(conn)?;
|
.execute(conn)?;
|
||||||
|
|
||||||
// Update the existing deleted URLs that are reinserted as no longer deleted
|
// Update the existing deleted URLs that are reinserted as no longer deleted
|
||||||
diesel::update(
|
diesel::update(
|
||||||
subscriptions::table.filter(
|
device_subscriptions::table.filter(
|
||||||
subscriptions::device_id
|
device_subscriptions::device_id
|
||||||
.eq(device_id)
|
.eq(device_id)
|
||||||
.and(subscriptions::url.eq_any(urls_to_update))
|
.and(device_subscriptions::podcast_url.eq_any(urls_to_update))
|
||||||
.and(subscriptions::deleted.eq(true)),
|
.and(device_subscriptions::deleted.eq(true)),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.set((
|
.set((
|
||||||
subscriptions::deleted.eq(false),
|
device_subscriptions::deleted.eq(false),
|
||||||
subscriptions::time_changed.eq(timestamp),
|
device_subscriptions::time_changed.eq(timestamp),
|
||||||
))
|
))
|
||||||
.execute(conn)?;
|
.execute(conn)?;
|
||||||
|
|
||||||
// Insert the new values into the database
|
// Insert the new values into the database
|
||||||
diesel::insert_into(subscriptions::table)
|
diesel::insert_into(device_subscriptions::table)
|
||||||
.values(
|
.values(
|
||||||
urls_to_insert
|
urls_to_insert
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|url| NewSubscription {
|
.map(|url| NewDeviceSubscription {
|
||||||
device_id,
|
device_id,
|
||||||
url: url.to_string(),
|
podcast_url: url.to_string(),
|
||||||
deleted: false,
|
deleted: false,
|
||||||
time_changed: timestamp,
|
time_changed: timestamp,
|
||||||
})
|
})
|
||||||
|
@ -134,9 +134,9 @@ impl Subscription {
|
||||||
let removed: HashSet<_> = removed.into_iter().collect();
|
let removed: HashSet<_> = removed.into_iter().collect();
|
||||||
|
|
||||||
pool.get()?.transaction(|conn| {
|
pool.get()?.transaction(|conn| {
|
||||||
let urls_in_db: HashSet<String> = subscriptions::table
|
let urls_in_db: HashSet<String> = device_subscriptions::table
|
||||||
.select(subscriptions::url)
|
.select(device_subscriptions::podcast_url)
|
||||||
.filter(subscriptions::device_id.eq(device_id))
|
.filter(device_subscriptions::device_id.eq(device_id))
|
||||||
.get_results(&mut pool.get()?)?
|
.get_results(&mut pool.get()?)?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect();
|
.collect();
|
||||||
|
@ -148,16 +148,16 @@ impl Subscription {
|
||||||
let urls_to_delete = removed.intersection(&urls_in_db);
|
let urls_to_delete = removed.intersection(&urls_in_db);
|
||||||
|
|
||||||
diesel::update(
|
diesel::update(
|
||||||
subscriptions::table.filter(
|
device_subscriptions::table.filter(
|
||||||
subscriptions::device_id
|
device_subscriptions::device_id
|
||||||
.eq(device_id)
|
.eq(device_id)
|
||||||
.and(subscriptions::url.eq_any(urls_to_delete))
|
.and(device_subscriptions::podcast_url.eq_any(urls_to_delete))
|
||||||
.and(subscriptions::deleted.eq(false)),
|
.and(device_subscriptions::deleted.eq(false)),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.set((
|
.set((
|
||||||
subscriptions::deleted.eq(true),
|
device_subscriptions::deleted.eq(true),
|
||||||
subscriptions::time_changed.eq(timestamp),
|
device_subscriptions::time_changed.eq(timestamp),
|
||||||
))
|
))
|
||||||
.execute(conn)?;
|
.execute(conn)?;
|
||||||
|
|
||||||
|
@ -166,16 +166,16 @@ impl Subscription {
|
||||||
let urls_to_update = added.intersection(&urls_in_db);
|
let urls_to_update = added.intersection(&urls_in_db);
|
||||||
|
|
||||||
diesel::update(
|
diesel::update(
|
||||||
subscriptions::table.filter(
|
device_subscriptions::table.filter(
|
||||||
subscriptions::device_id
|
device_subscriptions::device_id
|
||||||
.eq(device_id)
|
.eq(device_id)
|
||||||
.and(subscriptions::url.eq_any(urls_to_update))
|
.and(device_subscriptions::podcast_url.eq_any(urls_to_update))
|
||||||
.and(subscriptions::deleted.eq(true)),
|
.and(device_subscriptions::deleted.eq(true)),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.set((
|
.set((
|
||||||
subscriptions::deleted.eq(false),
|
device_subscriptions::deleted.eq(false),
|
||||||
subscriptions::time_changed.eq(timestamp),
|
device_subscriptions::time_changed.eq(timestamp),
|
||||||
))
|
))
|
||||||
.execute(conn)?;
|
.execute(conn)?;
|
||||||
|
|
||||||
|
@ -183,13 +183,13 @@ impl Subscription {
|
||||||
// added list
|
// added list
|
||||||
let urls_to_insert = added.difference(&urls_in_db);
|
let urls_to_insert = added.difference(&urls_in_db);
|
||||||
|
|
||||||
diesel::insert_into(subscriptions::table)
|
diesel::insert_into(device_subscriptions::table)
|
||||||
.values(
|
.values(
|
||||||
urls_to_insert
|
urls_to_insert
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|url| NewSubscription {
|
.map(|url| NewDeviceSubscription {
|
||||||
device_id,
|
device_id,
|
||||||
url: url.to_string(),
|
podcast_url: url.to_string(),
|
||||||
deleted: false,
|
deleted: false,
|
||||||
time_changed: timestamp,
|
time_changed: timestamp,
|
||||||
})
|
})
|
||||||
|
@ -206,12 +206,12 @@ impl Subscription {
|
||||||
device_id: i64,
|
device_id: i64,
|
||||||
timestamp: i64,
|
timestamp: i64,
|
||||||
) -> DbResult<Vec<Self>> {
|
) -> DbResult<Vec<Self>> {
|
||||||
Ok(subscriptions::table
|
Ok(device_subscriptions::table
|
||||||
.select(Self::as_select())
|
.select(Self::as_select())
|
||||||
.filter(
|
.filter(
|
||||||
subscriptions::device_id
|
device_subscriptions::device_id
|
||||||
.eq(device_id)
|
.eq(device_id)
|
||||||
.and(subscriptions::time_changed.ge(timestamp)),
|
.and(device_subscriptions::time_changed.ge(timestamp)),
|
||||||
)
|
)
|
||||||
.get_results(&mut pool.get()?)?)
|
.get_results(&mut pool.get()?)?)
|
||||||
}
|
}
|
|
@ -19,9 +19,9 @@ use crate::db::{schema::*, DbPool, DbResult};
|
||||||
#[diesel(check_for_backend(diesel::sqlite::Sqlite))]
|
#[diesel(check_for_backend(diesel::sqlite::Sqlite))]
|
||||||
pub struct EpisodeAction {
|
pub struct EpisodeAction {
|
||||||
id: i64,
|
id: i64,
|
||||||
subscription_id: i64,
|
|
||||||
device_id: Option<i64>,
|
device_id: Option<i64>,
|
||||||
episode: String,
|
podcast_url: String,
|
||||||
|
episode_url: String,
|
||||||
timestamp: Option<i64>,
|
timestamp: Option<i64>,
|
||||||
action: ActionType,
|
action: ActionType,
|
||||||
started: Option<i32>,
|
started: Option<i32>,
|
||||||
|
@ -33,9 +33,9 @@ pub struct EpisodeAction {
|
||||||
#[diesel(table_name = episode_actions)]
|
#[diesel(table_name = episode_actions)]
|
||||||
#[diesel(check_for_backend(diesel::sqlite::Sqlite))]
|
#[diesel(check_for_backend(diesel::sqlite::Sqlite))]
|
||||||
pub struct NewEpisodeAction {
|
pub struct NewEpisodeAction {
|
||||||
subscription_id: i64,
|
|
||||||
device_id: Option<i64>,
|
device_id: Option<i64>,
|
||||||
episode: String,
|
podcast_url: String,
|
||||||
|
episode_url: String,
|
||||||
timestamp: Option<i64>,
|
timestamp: Option<i64>,
|
||||||
action: ActionType,
|
action: ActionType,
|
||||||
started: Option<i32>,
|
started: Option<i32>,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
pub mod device;
|
pub mod device;
|
||||||
|
pub mod device_subscription;
|
||||||
pub mod episode_action;
|
pub mod episode_action;
|
||||||
pub mod session;
|
pub mod session;
|
||||||
pub mod subscription;
|
|
||||||
pub mod user;
|
pub mod user;
|
||||||
|
|
|
@ -13,10 +13,10 @@ impl gpodder::SubscriptionRepository for SqliteRepository {
|
||||||
&self,
|
&self,
|
||||||
user: &gpodder::User,
|
user: &gpodder::User,
|
||||||
) -> Result<Vec<String>, gpodder::AuthErr> {
|
) -> Result<Vec<String>, gpodder::AuthErr> {
|
||||||
Ok(subscriptions::table
|
Ok(device_subscriptions::table
|
||||||
.inner_join(devices::table)
|
.inner_join(devices::table)
|
||||||
.filter(devices::user_id.eq(user.id))
|
.filter(devices::user_id.eq(user.id))
|
||||||
.select(subscriptions::url)
|
.select(device_subscriptions::podcast_url)
|
||||||
.distinct()
|
.distinct()
|
||||||
.get_results(&mut self.pool.get()?)?)
|
.get_results(&mut self.pool.get()?)?)
|
||||||
}
|
}
|
||||||
|
@ -26,14 +26,14 @@ impl gpodder::SubscriptionRepository for SqliteRepository {
|
||||||
user: &gpodder::User,
|
user: &gpodder::User,
|
||||||
device_id: &str,
|
device_id: &str,
|
||||||
) -> Result<Vec<String>, gpodder::AuthErr> {
|
) -> Result<Vec<String>, gpodder::AuthErr> {
|
||||||
Ok(subscriptions::table
|
Ok(device_subscriptions::table
|
||||||
.inner_join(devices::table)
|
.inner_join(devices::table)
|
||||||
.filter(
|
.filter(
|
||||||
devices::user_id
|
devices::user_id
|
||||||
.eq(user.id)
|
.eq(user.id)
|
||||||
.and(devices::device_id.eq(device_id)),
|
.and(devices::device_id.eq(device_id)),
|
||||||
)
|
)
|
||||||
.select(subscriptions::url)
|
.select(device_subscriptions::podcast_url)
|
||||||
.get_results(&mut self.pool.get()?)?)
|
.get_results(&mut self.pool.get()?)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,9 +61,9 @@ impl gpodder::SubscriptionRepository for SqliteRepository {
|
||||||
// on conflict. Therefore, we instead calculate which URLs should be inserted and which
|
// on conflict. Therefore, we instead calculate which URLs should be inserted and which
|
||||||
// updated, so we avoid conflicts.
|
// updated, so we avoid conflicts.
|
||||||
let urls: HashSet<String> = urls.into_iter().collect();
|
let urls: HashSet<String> = urls.into_iter().collect();
|
||||||
let urls_in_db: HashSet<String> = subscriptions::table
|
let urls_in_db: HashSet<String> = device_subscriptions::table
|
||||||
.select(subscriptions::url)
|
.select(device_subscriptions::podcast_url)
|
||||||
.filter(subscriptions::device_id.eq(device.id))
|
.filter(device_subscriptions::device_id.eq(device.id))
|
||||||
.get_results(conn)?
|
.get_results(conn)?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect();
|
.collect();
|
||||||
|
@ -81,41 +81,41 @@ impl gpodder::SubscriptionRepository for SqliteRepository {
|
||||||
|
|
||||||
// Mark the URLs to delete as properly deleted
|
// Mark the URLs to delete as properly deleted
|
||||||
diesel::update(
|
diesel::update(
|
||||||
subscriptions::table.filter(
|
device_subscriptions::table.filter(
|
||||||
subscriptions::device_id
|
device_subscriptions::device_id
|
||||||
.eq(device.id)
|
.eq(device.id)
|
||||||
.and(subscriptions::url.eq_any(urls_to_delete)),
|
.and(device_subscriptions::podcast_url.eq_any(urls_to_delete)),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.set((
|
.set((
|
||||||
subscriptions::deleted.eq(true),
|
device_subscriptions::deleted.eq(true),
|
||||||
subscriptions::time_changed.eq(timestamp),
|
device_subscriptions::time_changed.eq(timestamp),
|
||||||
))
|
))
|
||||||
.execute(conn)?;
|
.execute(conn)?;
|
||||||
|
|
||||||
// Update the existing deleted URLs that are reinserted as no longer deleted
|
// Update the existing deleted URLs that are reinserted as no longer deleted
|
||||||
diesel::update(
|
diesel::update(
|
||||||
subscriptions::table.filter(
|
device_subscriptions::table.filter(
|
||||||
subscriptions::device_id
|
device_subscriptions::device_id
|
||||||
.eq(device.id)
|
.eq(device.id)
|
||||||
.and(subscriptions::url.eq_any(urls_to_update))
|
.and(device_subscriptions::podcast_url.eq_any(urls_to_update))
|
||||||
.and(subscriptions::deleted.eq(true)),
|
.and(device_subscriptions::deleted.eq(true)),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.set((
|
.set((
|
||||||
subscriptions::deleted.eq(false),
|
device_subscriptions::deleted.eq(false),
|
||||||
subscriptions::time_changed.eq(timestamp),
|
device_subscriptions::time_changed.eq(timestamp),
|
||||||
))
|
))
|
||||||
.execute(conn)?;
|
.execute(conn)?;
|
||||||
|
|
||||||
// Insert the new values into the database
|
// Insert the new values into the database
|
||||||
diesel::insert_into(subscriptions::table)
|
diesel::insert_into(device_subscriptions::table)
|
||||||
.values(
|
.values(
|
||||||
urls_to_insert
|
urls_to_insert
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|url| db::NewSubscription {
|
.map(|url| db::NewDeviceSubscription {
|
||||||
device_id: device.id,
|
device_id: device.id,
|
||||||
url: url.to_string(),
|
podcast_url: url.to_string(),
|
||||||
deleted: false,
|
deleted: false,
|
||||||
time_changed: timestamp,
|
time_changed: timestamp,
|
||||||
})
|
})
|
||||||
|
@ -154,9 +154,9 @@ impl gpodder::SubscriptionRepository for SqliteRepository {
|
||||||
)
|
)
|
||||||
.get_result(conn)?;
|
.get_result(conn)?;
|
||||||
|
|
||||||
let urls_in_db: HashSet<String> = subscriptions::table
|
let urls_in_db: HashSet<String> = device_subscriptions::table
|
||||||
.select(subscriptions::url)
|
.select(device_subscriptions::podcast_url)
|
||||||
.filter(subscriptions::device_id.eq(device.id))
|
.filter(device_subscriptions::device_id.eq(device.id))
|
||||||
.get_results(conn)?
|
.get_results(conn)?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect();
|
.collect();
|
||||||
|
@ -168,16 +168,16 @@ impl gpodder::SubscriptionRepository for SqliteRepository {
|
||||||
let urls_to_delete = remove.intersection(&urls_in_db);
|
let urls_to_delete = remove.intersection(&urls_in_db);
|
||||||
|
|
||||||
diesel::update(
|
diesel::update(
|
||||||
subscriptions::table.filter(
|
device_subscriptions::table.filter(
|
||||||
subscriptions::device_id
|
device_subscriptions::device_id
|
||||||
.eq(device.id)
|
.eq(device.id)
|
||||||
.and(subscriptions::url.eq_any(urls_to_delete))
|
.and(device_subscriptions::podcast_url.eq_any(urls_to_delete))
|
||||||
.and(subscriptions::deleted.eq(false)),
|
.and(device_subscriptions::deleted.eq(false)),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.set((
|
.set((
|
||||||
subscriptions::deleted.eq(true),
|
device_subscriptions::deleted.eq(true),
|
||||||
subscriptions::time_changed.eq(timestamp),
|
device_subscriptions::time_changed.eq(timestamp),
|
||||||
))
|
))
|
||||||
.execute(conn)?;
|
.execute(conn)?;
|
||||||
|
|
||||||
|
@ -186,16 +186,16 @@ impl gpodder::SubscriptionRepository for SqliteRepository {
|
||||||
let urls_to_update = add.intersection(&urls_in_db);
|
let urls_to_update = add.intersection(&urls_in_db);
|
||||||
|
|
||||||
diesel::update(
|
diesel::update(
|
||||||
subscriptions::table.filter(
|
device_subscriptions::table.filter(
|
||||||
subscriptions::device_id
|
device_subscriptions::device_id
|
||||||
.eq(device.id)
|
.eq(device.id)
|
||||||
.and(subscriptions::url.eq_any(urls_to_update))
|
.and(device_subscriptions::podcast_url.eq_any(urls_to_update))
|
||||||
.and(subscriptions::deleted.eq(true)),
|
.and(device_subscriptions::deleted.eq(true)),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.set((
|
.set((
|
||||||
subscriptions::deleted.eq(false),
|
device_subscriptions::deleted.eq(false),
|
||||||
subscriptions::time_changed.eq(timestamp),
|
device_subscriptions::time_changed.eq(timestamp),
|
||||||
))
|
))
|
||||||
.execute(conn)?;
|
.execute(conn)?;
|
||||||
|
|
||||||
|
@ -203,13 +203,13 @@ impl gpodder::SubscriptionRepository for SqliteRepository {
|
||||||
// added list
|
// added list
|
||||||
let urls_to_insert = add.difference(&urls_in_db);
|
let urls_to_insert = add.difference(&urls_in_db);
|
||||||
|
|
||||||
diesel::insert_into(subscriptions::table)
|
diesel::insert_into(device_subscriptions::table)
|
||||||
.values(
|
.values(
|
||||||
urls_to_insert
|
urls_to_insert
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|url| db::NewSubscription {
|
.map(|url| db::NewDeviceSubscription {
|
||||||
device_id: device.id,
|
device_id: device.id,
|
||||||
url: url.to_string(),
|
podcast_url: url.to_string(),
|
||||||
deleted: false,
|
deleted: false,
|
||||||
time_changed: timestamp,
|
time_changed: timestamp,
|
||||||
})
|
})
|
||||||
|
@ -231,23 +231,23 @@ impl gpodder::SubscriptionRepository for SqliteRepository {
|
||||||
) -> Result<(i64, Vec<String>, Vec<String>), gpodder::AuthErr> {
|
) -> Result<(i64, Vec<String>, Vec<String>), gpodder::AuthErr> {
|
||||||
let (mut timestamp, mut added, mut removed) = (0, Vec::new(), Vec::new());
|
let (mut timestamp, mut added, mut removed) = (0, Vec::new(), Vec::new());
|
||||||
|
|
||||||
let query = subscriptions::table
|
let query = device_subscriptions::table
|
||||||
.inner_join(devices::table)
|
.inner_join(devices::table)
|
||||||
.filter(
|
.filter(
|
||||||
devices::user_id
|
devices::user_id
|
||||||
.eq(user.id)
|
.eq(user.id)
|
||||||
.and(devices::device_id.eq(device_id))
|
.and(devices::device_id.eq(device_id))
|
||||||
.and(subscriptions::time_changed.ge(since)),
|
.and(device_subscriptions::time_changed.ge(since)),
|
||||||
)
|
)
|
||||||
.select(db::Subscription::as_select());
|
.select(db::DeviceSubscription::as_select());
|
||||||
|
|
||||||
for sub in query.load_iter(&mut self.pool.get()?)? {
|
for sub in query.load_iter(&mut self.pool.get()?)? {
|
||||||
let sub = sub?;
|
let sub = sub?;
|
||||||
|
|
||||||
if sub.deleted {
|
if sub.deleted {
|
||||||
removed.push(sub.url);
|
removed.push(sub.podcast_url);
|
||||||
} else {
|
} else {
|
||||||
added.push(sub.url);
|
added.push(sub.podcast_url);
|
||||||
}
|
}
|
||||||
|
|
||||||
timestamp = timestamp.max(sub.time_changed);
|
timestamp = timestamp.max(sub.time_changed);
|
||||||
|
|
|
@ -1,5 +1,15 @@
|
||||||
// @generated automatically by Diesel CLI.
|
// @generated automatically by Diesel CLI.
|
||||||
|
|
||||||
|
diesel::table! {
|
||||||
|
device_subscriptions (id) {
|
||||||
|
id -> BigInt,
|
||||||
|
device_id -> BigInt,
|
||||||
|
podcast_url -> Text,
|
||||||
|
time_changed -> BigInt,
|
||||||
|
deleted -> Bool,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
diesel::table! {
|
diesel::table! {
|
||||||
devices (id) {
|
devices (id) {
|
||||||
id -> BigInt,
|
id -> BigInt,
|
||||||
|
@ -14,9 +24,9 @@ diesel::table! {
|
||||||
diesel::table! {
|
diesel::table! {
|
||||||
episode_actions (id) {
|
episode_actions (id) {
|
||||||
id -> BigInt,
|
id -> BigInt,
|
||||||
subscription_id -> BigInt,
|
|
||||||
device_id -> Nullable<BigInt>,
|
device_id -> Nullable<BigInt>,
|
||||||
episode -> Text,
|
podcast_url -> Text,
|
||||||
|
episode_url -> Text,
|
||||||
timestamp -> Nullable<BigInt>,
|
timestamp -> Nullable<BigInt>,
|
||||||
action -> Text,
|
action -> Text,
|
||||||
started -> Nullable<Integer>,
|
started -> Nullable<Integer>,
|
||||||
|
@ -32,16 +42,6 @@ diesel::table! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
diesel::table! {
|
|
||||||
subscriptions (id) {
|
|
||||||
id -> BigInt,
|
|
||||||
device_id -> BigInt,
|
|
||||||
url -> Text,
|
|
||||||
time_changed -> BigInt,
|
|
||||||
deleted -> Bool,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
diesel::table! {
|
diesel::table! {
|
||||||
users (id) {
|
users (id) {
|
||||||
id -> BigInt,
|
id -> BigInt,
|
||||||
|
@ -50,16 +50,15 @@ diesel::table! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
diesel::joinable!(device_subscriptions -> devices (device_id));
|
||||||
diesel::joinable!(devices -> users (user_id));
|
diesel::joinable!(devices -> users (user_id));
|
||||||
diesel::joinable!(episode_actions -> devices (device_id));
|
diesel::joinable!(episode_actions -> devices (device_id));
|
||||||
diesel::joinable!(episode_actions -> subscriptions (subscription_id));
|
|
||||||
diesel::joinable!(sessions -> users (user_id));
|
diesel::joinable!(sessions -> users (user_id));
|
||||||
diesel::joinable!(subscriptions -> devices (device_id));
|
|
||||||
|
|
||||||
diesel::allow_tables_to_appear_in_same_query!(
|
diesel::allow_tables_to_appear_in_same_query!(
|
||||||
|
device_subscriptions,
|
||||||
devices,
|
devices,
|
||||||
episode_actions,
|
episode_actions,
|
||||||
sessions,
|
sessions,
|
||||||
subscriptions,
|
|
||||||
users,
|
users,
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue