create table users ( id integer primary key not null, username text unique not null, password_hash text not null ); create table sessions ( id bigint primary key not null, user_id bigint not null references users (id) on delete cascade, last_seen bigint not null, unique (id, user_id) ); create table devices ( id integer primary key not null, device_id text not null, user_id bigint not null references users (id) on delete cascade, sync_group_id bigint references sync_groups (id) on delete set null, caption text not null, type text not null, unique (user_id, device_id) ); create table sync_groups ( id integer primary key not null ); create table device_subscriptions ( id integer primary key not null, device_id bigint not null references devices (id) on delete cascade, podcast_url text not null, time_changed bigint not null, deleted boolean not null default false, unique (device_id, podcast_url) ); create table episode_actions ( id integer primary key not null, user_id bigint not null references users (id) on delete cascade, -- Can be null, as the device is not always provided device_id bigint references devices (id) on delete set null, podcast_url text not null, episode_url text not null, time_changed bigint not null, timestamp bigint, action text not null, started integer, position integer, total integer, -- Position should be set if the action type is "Play" and null otherwise check ((action = "play") = (position is not null)), -- Started and position can only be set if the action type is "Play" check (action = "play" or (started is null and position is null)), -- Started and position should be provided together check ((started is null) = (total is null)) );