The clean & modern RSS server that doesn't give you any crap. https://thearsse.com/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

203 lines
12 KiB

-- SPDX-License-Identifier: MIT
-- Copyright 2017 J. King, Dustin Wilson et al.
-- See LICENSE and AUTHORS files for details
-- Create a temporary table mapping old article IDs to new article IDs per-user.
-- Any articles which have only one subscription will be unchanged, which will
-- limit the amount of disruption
create temp table arsse_articles_map(
article int not null,
subscription int not null,
id integer primary key autoincrement
);
replace into temp.sqlite_sequence(name,seq) select 'arsse_articles_map', max(id) from arsse_articles;
insert into arsse_articles_map(article, subscription)
select
a.id as article,
s.id as subscription
from arsse_articles as a join arsse_subscriptions as s using(feed)
where feed in (
select feed from (select feed, count(*) as count from arsse_subscriptions group by feed) as c where count > 1
);
insert into arsse_articles_map(article, subscription, id)
select
a.id as article,
s.id as subscription,
a.id as id
from arsse_articles as a join arsse_subscriptions as s using(feed)
where feed in (
select feed from (select feed, count(*) as count from arsse_subscriptions group by feed) as c where count = 1
);
-- Create a new articles table which combines the marks table but does not include content
create table arsse_articles_new(
-- metadata for entries in newsfeeds, including user state
id integer primary key, -- sequence number
subscription integer not null references arsse_subscriptions(id) on delete cascade on update cascade, -- associated subscription
read int not null default 0, -- whether the article has been read
starred int not null default 0, -- whether the article is starred
hidden int not null default 0, -- whether the article should be excluded from selection by default
published text, -- time of original publication
edited text, -- time of last edit by author
modified text not null default CURRENT_TIMESTAMP, -- time when article was last modified in database pursuant to an authorial edit
marked text, -- time at which an article was last modified by the user
url text, -- URL of article
title text collate nocase, -- article title
author text collate nocase, -- author's name
guid text, -- a nominally globally unique identifier for the article, from the feed
url_title_hash text not null, -- hash of URL + title; used when checking for updates and for identification if there is no guid
url_content_hash text not null, -- hash of URL + content + enclosure URL + enclosure content type; used when checking for updates and for identification if there is no guid
title_content_hash text not null, -- hash of title + content + enclosure URL + enclosure content type; used when checking for updates and for identification if there is no guid
touched int not null default 0, -- field used internally while marking; should normally be left as 0
note text not null default '' -- Tiny Tiny RSS freeform user note
);
insert into arsse_articles_new
select
i.id,
i.subscription,
coalesce(m.read,0),
coalesce(m.starred,0),
coalesce(m.hidden,0),
a.published,
a.edited,
a.modified,
m.modified,
a.url,
a.title,
a.author,
a.guid,
a.url_title_hash,
a.url_content_hash,
a.title_content_hash,
0,
coalesce(m.note,'')
from arsse_articles_map as i
left join arsse_articles as a on a.id = i.article
left join arsse_marks as m on a.id = m.article and m.subscription = i.subscription;
-- Create a new table to hold article content
create table arsse_article_contents(
-- contents of articles, which is typically large text
id integer primary key references arsse_articles(id) on delete cascade on update cascade, -- reference to the article ID
content text -- the contents
);
insert into arsse_article_contents
select
m.id,
case when s.scrape = 0 then a.content else coalesce(a.content_scraped, a.content) end
from arsse_articles_map as m
left join arsse_articles as a on a.id = m.article
left join arsse_subscriptions as s on s.id = m.subscription;
-- Create one edition for each renumbered article, and delete any editions for obsolete articles
insert into arsse_editions(article, modified)
select
m.id, e.modified
from arsse_editions as e
join arsse_articles_map as m using(article)
where m.id <> article
order by m.id, modified;
delete from arsse_editions where article in (select article from arsse_articles_map where id <> article) or article not in (select id from arsse_articles_map);
-- Create enclures for renumbered articles and delete obsolete enclosures
insert into arsse_enclosures(article, url, type)
select
m.id, url, type
from arsse_articles_map as m
join arsse_enclosures as e on m.article = e.article
where m.id <> m.article;
delete from arsse_enclosures where article in (select article from arsse_articles_map where id <> article) or article not in (select id from arsse_articles_map);
-- Create categories for renumbered articles and delete obsolete categories
insert into arsse_categories(article, name)
select
m.id, name
from arsse_articles_map as m
join arsse_categories as c on m.article = c.article
where m.id <> m.article;
delete from arsse_categories where article in (select article from arsse_articles_map where id <> article) or article not in (select id from arsse_articles_map);
-- Create a new label-associations table which omits the subscription column and populate it with new data
create table arsse_label_members_new(
-- label assignments for articles
label integer not null references arsse_labels(id) on delete cascade, -- label ID associated to an article; label IDs belong to a user
article integer not null references arsse_articles(id) on delete cascade, -- article associated to a label
assigned int not null default 1, -- whether the association is current, to support soft deletion
modified text not null default CURRENT_TIMESTAMP, -- time at which the association was last made or unmade
primary key(label,article) -- only one association of a given label to a given article
) without rowid;
insert into arsse_label_members_new
select
label, m.id, assigned, l.modified
from arsse_articles_map as m
join arsse_label_members as l using(article, subscription);
-- Create a new subscriptions table which combines the feeds table
create table arsse_subscriptions_new(
-- users' subscriptions to newsfeeds, with settings
id integer primary key, -- sequence number
owner text not null references arsse_users(id) on delete cascade on update cascade, -- owner of subscription
url text not null, -- URL of feed
deleted int not null default 0, -- soft-delete flag
feed_title text collate nocase, -- feed title
title text collate nocase, -- user-supplied title, which overrides the feed title when set
folder integer references arsse_folders(id) on delete cascade, -- TT-RSS category (nestable); the first-level category (which acts as Nextcloud folder) is joined in when needed
modified text not null default CURRENT_TIMESTAMP, -- time at which subscription properties were last modified by the user
last_mod text, -- time at which the feed last actually changed at the foreign host
etag text not null default '', -- HTTP ETag hash used for cache validation, changes each time the content changes
next_fetch text, -- time at which the feed should next be fetched
added text not null default CURRENT_TIMESTAMP, -- time at which feed was added
source text, -- URL of site to which the feed belongs
updated text, -- time at which the feed was last fetched
err_count integer not null default 0, -- count of successive times update resulted in error since last successful update
err_msg text, -- last error message
size integer not null default 0, -- number of articles in the feed at last fetch
icon integer references arsse_icons(id) on delete set null, -- numeric identifier of any associated icon
order_type int not null default 0, -- Nextcloud sort order
pinned int not null default 0, -- whether feed is pinned (always sorts at top)
scrape int not null default 0, -- whether the user has requested scraping content from source articles
keep_rule text, -- Regular expression the subscription's articles must match to avoid being hidden
block_rule text, -- Regular expression the subscription's articles must not match to avoid being hidden
unique(owner,url) -- a URL with particular credentials should only appear once
);
insert into arsse_subscriptions_new
select
s.id,
s.owner,
f.url,
0,
f.title,
s.title,
s.folder,
s.modified,
f.modified,
f.etag,
f.next_fetch,
s.added,
f.source,
f.updated,
f.err_count,
f.err_msg,
f.size,
f.icon,
s.order_type,
s.pinned,
s.scrape,
s.keep_rule,
s.block_rule
from arsse_subscriptions as s left join arsse_feeds as f on s.feed = f.id;
-- Delete the old tables and rename the new ones
drop table arsse_label_members;
drop table arsse_subscriptions;
drop table arsse_feeds;
drop table arsse_articles;
drop table arsse_marks;
drop table arsse_articles_map;
alter table arsse_subscriptions_new rename to arsse_subscriptions;
alter table arsse_articles_new rename to arsse_articles;
alter table arsse_label_members_new rename to arsse_label_members;
-- set version marker
pragma user_version = 8;
update arsse_meta set value = '8' where "key" = 'schema_version';