257 lines
10 KiB
SQL
257 lines
10 KiB
SQL
CREATE TABLE IF NOT EXISTS sources (
|
|
id INTEGER PRIMARY KEY,
|
|
kind TEXT NOT NULL CHECK (kind IN ('jmap','imap','caldav','carddav','webdav','managesieve','maildir','exchange_ews','exchange_graph','takeout')),
|
|
session_url TEXT NOT NULL,
|
|
account_id TEXT NOT NULL,
|
|
account_name TEXT,
|
|
username TEXT NOT NULL,
|
|
UNIQUE (kind, session_url, account_id)
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS blobs (
|
|
id INTEGER PRIMARY KEY,
|
|
hash BLOB NOT NULL UNIQUE,
|
|
data BLOB NOT NULL
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS blobs_hash_idx ON blobs (hash);
|
|
|
|
CREATE TABLE IF NOT EXISTS sync_id_jmap (
|
|
source_id INTEGER NOT NULL REFERENCES sources(id) ON DELETE CASCADE,
|
|
type_name TEXT NOT NULL,
|
|
jmap_id TEXT NOT NULL,
|
|
local_id INTEGER NOT NULL,
|
|
PRIMARY KEY (source_id, type_name, jmap_id),
|
|
UNIQUE (source_id, type_name, local_id)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS sync_id_jmap_local_idx
|
|
ON sync_id_jmap (type_name, local_id);
|
|
|
|
CREATE TABLE IF NOT EXISTS sync_state_jmap (
|
|
source_id INTEGER NOT NULL REFERENCES sources(id) ON DELETE CASCADE,
|
|
type_name TEXT NOT NULL,
|
|
state TEXT NOT NULL,
|
|
PRIMARY KEY (source_id, type_name)
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS sync_id_imap (
|
|
source_id INTEGER NOT NULL REFERENCES sources(id) ON DELETE CASCADE,
|
|
type_name TEXT NOT NULL CHECK (type_name IN ('mailbox','email')),
|
|
folder TEXT NOT NULL,
|
|
uidvalidity INTEGER NOT NULL,
|
|
uid INTEGER NOT NULL,
|
|
local_id INTEGER NOT NULL,
|
|
PRIMARY KEY (source_id, type_name, folder, uidvalidity, uid),
|
|
UNIQUE (source_id, type_name, local_id)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS sync_id_imap_folder_idx
|
|
ON sync_id_imap (source_id, type_name, folder);
|
|
|
|
CREATE TABLE IF NOT EXISTS imap_folder_state (
|
|
source_id INTEGER NOT NULL REFERENCES sources(id) ON DELETE CASCADE,
|
|
folder TEXT NOT NULL,
|
|
uidvalidity INTEGER NOT NULL,
|
|
uidnext INTEGER NOT NULL,
|
|
last_seen TEXT NOT NULL,
|
|
PRIMARY KEY (source_id, folder)
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS sync_id_dav (
|
|
source_id INTEGER NOT NULL REFERENCES sources(id) ON DELETE CASCADE,
|
|
type_name TEXT NOT NULL CHECK (type_name IN (
|
|
'calendar','calendarevent',
|
|
'addressbook','contactcard',
|
|
'filenode')),
|
|
collection_href TEXT NOT NULL,
|
|
item_href TEXT NOT NULL,
|
|
etag TEXT NOT NULL DEFAULT '',
|
|
local_id INTEGER NOT NULL,
|
|
PRIMARY KEY (source_id, type_name, item_href),
|
|
UNIQUE (source_id, type_name, local_id)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS sync_id_dav_collection_idx
|
|
ON sync_id_dav (source_id, type_name, collection_href);
|
|
|
|
CREATE TABLE IF NOT EXISTS sync_id_managesieve (
|
|
source_id INTEGER NOT NULL REFERENCES sources(id) ON DELETE CASCADE,
|
|
name TEXT NOT NULL,
|
|
local_id INTEGER NOT NULL,
|
|
PRIMARY KEY (source_id, name),
|
|
UNIQUE (source_id, local_id)
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS sync_id_maildir (
|
|
source_id INTEGER NOT NULL REFERENCES sources(id) ON DELETE CASCADE,
|
|
type_name TEXT NOT NULL CHECK (type_name IN ('mailbox','email')),
|
|
folder TEXT NOT NULL,
|
|
unique_id TEXT NOT NULL,
|
|
local_id INTEGER NOT NULL,
|
|
PRIMARY KEY (source_id, type_name, folder, unique_id),
|
|
UNIQUE (source_id, type_name, local_id)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS sync_id_maildir_folder_idx
|
|
ON sync_id_maildir (source_id, type_name, folder);
|
|
|
|
CREATE TABLE IF NOT EXISTS sync_id_exchange_ews (
|
|
source_id INTEGER NOT NULL REFERENCES sources(id) ON DELETE CASCADE,
|
|
type_name TEXT NOT NULL CHECK (type_name IN (
|
|
'mailbox','calendar','addressbook',
|
|
'email','calendarevent','contactcard')),
|
|
folder_id TEXT NOT NULL DEFAULT '',
|
|
item_id TEXT NOT NULL,
|
|
change_key TEXT NOT NULL DEFAULT '',
|
|
sync_state TEXT NOT NULL DEFAULT '',
|
|
local_id INTEGER NOT NULL,
|
|
PRIMARY KEY (source_id, type_name, item_id),
|
|
UNIQUE (source_id, type_name, local_id)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS sync_id_exchange_ews_folder_idx
|
|
ON sync_id_exchange_ews (source_id, type_name, folder_id);
|
|
|
|
CREATE TABLE IF NOT EXISTS sync_id_exchange_graph (
|
|
source_id INTEGER NOT NULL REFERENCES sources(id) ON DELETE CASCADE,
|
|
type_name TEXT NOT NULL CHECK (type_name IN (
|
|
'mailbox','email',
|
|
'calendar','calendarevent',
|
|
'addressbook','contactcard')),
|
|
graph_id TEXT NOT NULL,
|
|
local_id INTEGER NOT NULL,
|
|
PRIMARY KEY (source_id, type_name, graph_id),
|
|
UNIQUE (source_id, type_name, local_id)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS sync_id_exchange_graph_type_idx
|
|
ON sync_id_exchange_graph (source_id, type_name);
|
|
|
|
CREATE TABLE IF NOT EXISTS mailboxes (
|
|
id INTEGER PRIMARY KEY,
|
|
name TEXT NOT NULL,
|
|
parent_id INTEGER REFERENCES mailboxes(id) ON DELETE RESTRICT,
|
|
role TEXT,
|
|
sort_order INTEGER NOT NULL DEFAULT 0,
|
|
is_subscribed INTEGER NOT NULL DEFAULT 1,
|
|
UNIQUE (parent_id, name)
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS emails (
|
|
id INTEGER PRIMARY KEY,
|
|
blob_id INTEGER NOT NULL REFERENCES blobs(id),
|
|
received_at TEXT NOT NULL,
|
|
mailbox_ids TEXT NOT NULL CHECK (json_valid(mailbox_ids)),
|
|
keywords TEXT NOT NULL DEFAULT '[]' CHECK (json_valid(keywords)),
|
|
message_match TEXT NOT NULL DEFAULT '{}' CHECK (json_valid(message_match))
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS emails_blob_idx ON emails (blob_id);
|
|
|
|
CREATE TABLE IF NOT EXISTS identities (
|
|
id INTEGER PRIMARY KEY,
|
|
name TEXT NOT NULL DEFAULT '',
|
|
email TEXT NOT NULL,
|
|
reply_to TEXT CHECK (reply_to IS NULL OR json_valid(reply_to)),
|
|
bcc TEXT CHECK (bcc IS NULL OR json_valid(bcc)),
|
|
text_signature TEXT NOT NULL DEFAULT '',
|
|
html_signature TEXT NOT NULL DEFAULT ''
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS sieve_scripts (
|
|
id INTEGER PRIMARY KEY,
|
|
name TEXT,
|
|
is_active INTEGER NOT NULL DEFAULT 0,
|
|
blob_id INTEGER NOT NULL REFERENCES blobs(id),
|
|
UNIQUE (name)
|
|
);
|
|
|
|
CREATE UNIQUE INDEX IF NOT EXISTS sieve_scripts_one_active_idx
|
|
ON sieve_scripts (is_active) WHERE is_active = 1;
|
|
|
|
CREATE TABLE IF NOT EXISTS address_books (
|
|
id INTEGER PRIMARY KEY,
|
|
name TEXT NOT NULL,
|
|
description TEXT,
|
|
sort_order INTEGER NOT NULL DEFAULT 0,
|
|
is_default INTEGER NOT NULL DEFAULT 0,
|
|
is_subscribed INTEGER NOT NULL DEFAULT 1
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS contact_cards (
|
|
id INTEGER PRIMARY KEY,
|
|
uid TEXT NOT NULL UNIQUE,
|
|
address_book_ids TEXT NOT NULL CHECK (json_valid(address_book_ids)),
|
|
data TEXT NOT NULL CHECK (json_valid(data))
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS calendars (
|
|
id INTEGER PRIMARY KEY,
|
|
name TEXT NOT NULL,
|
|
description TEXT,
|
|
color TEXT,
|
|
sort_order INTEGER NOT NULL DEFAULT 0,
|
|
is_subscribed INTEGER NOT NULL DEFAULT 1,
|
|
is_visible INTEGER NOT NULL DEFAULT 1,
|
|
is_default INTEGER NOT NULL DEFAULT 0,
|
|
include_in_availability TEXT NOT NULL DEFAULT 'all'
|
|
CHECK (include_in_availability IN ('all','attending','none')),
|
|
default_alerts_with_time TEXT CHECK (default_alerts_with_time IS NULL
|
|
OR json_valid(default_alerts_with_time)),
|
|
default_alerts_without_time TEXT CHECK (default_alerts_without_time IS NULL
|
|
OR json_valid(default_alerts_without_time)),
|
|
time_zone TEXT
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS calendar_events (
|
|
id INTEGER PRIMARY KEY,
|
|
calendar_ids TEXT NOT NULL CHECK (json_valid(calendar_ids)),
|
|
is_draft INTEGER NOT NULL DEFAULT 0,
|
|
use_default_alerts INTEGER NOT NULL DEFAULT 0,
|
|
data TEXT NOT NULL CHECK (json_valid(data)),
|
|
data_type TEXT NOT NULL DEFAULT 'Event'
|
|
CHECK (data_type IN ('Event','Task','Note','Group'))
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS participant_identities (
|
|
id INTEGER PRIMARY KEY,
|
|
name TEXT NOT NULL DEFAULT '',
|
|
calendar_address TEXT NOT NULL,
|
|
is_default INTEGER NOT NULL DEFAULT 0
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS file_nodes (
|
|
id INTEGER PRIMARY KEY,
|
|
parent_id INTEGER REFERENCES file_nodes(id) ON DELETE RESTRICT,
|
|
node_type TEXT NOT NULL
|
|
CHECK (node_type IN ('file','directory','symlink')),
|
|
blob_id INTEGER REFERENCES blobs(id),
|
|
target TEXT CHECK (target IS NULL OR json_valid(target)),
|
|
name TEXT NOT NULL,
|
|
media_type TEXT,
|
|
created TEXT NOT NULL,
|
|
modified TEXT,
|
|
is_subscribed INTEGER NOT NULL DEFAULT 1,
|
|
role TEXT,
|
|
UNIQUE (parent_id, name)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS file_nodes_parent_idx ON file_nodes (parent_id);
|
|
CREATE INDEX IF NOT EXISTS file_nodes_blob_idx ON file_nodes (blob_id);
|
|
|
|
CREATE TABLE IF NOT EXISTS sync_id_takeout (
|
|
source_id INTEGER NOT NULL REFERENCES sources(id) ON DELETE CASCADE,
|
|
type_name TEXT NOT NULL CHECK (type_name IN (
|
|
'mailbox','email',
|
|
'addressbook','contactcard',
|
|
'calendar','calendarevent')),
|
|
source_obj_id TEXT NOT NULL,
|
|
local_id INTEGER NOT NULL,
|
|
PRIMARY KEY (source_id, type_name, source_obj_id),
|
|
UNIQUE (source_id, type_name, local_id)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS sync_id_takeout_type_idx
|
|
ON sync_id_takeout (source_id, type_name);
|