clickclack/infra/migrations/sqlite/0001_initial.sql
2026-05-08 05:36:16 +01:00

151 lines
4.8 KiB
SQL

CREATE TABLE IF NOT EXISTS users (
id TEXT PRIMARY KEY,
display_name TEXT NOT NULL,
avatar_url TEXT NOT NULL DEFAULT '',
created_at TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS identities (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
provider TEXT NOT NULL,
provider_subject TEXT NOT NULL,
email TEXT NOT NULL DEFAULT '',
created_at TEXT NOT NULL,
UNIQUE(provider, provider_subject)
);
CREATE TABLE IF NOT EXISTS workspaces (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
slug TEXT NOT NULL UNIQUE,
created_at TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS workspace_members (
workspace_id TEXT NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
role TEXT NOT NULL,
created_at TEXT NOT NULL,
PRIMARY KEY (workspace_id, user_id)
);
CREATE TABLE IF NOT EXISTS channels (
id TEXT PRIMARY KEY,
workspace_id TEXT NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
name TEXT NOT NULL,
kind TEXT NOT NULL,
created_at TEXT NOT NULL,
archived_at TEXT,
UNIQUE(workspace_id, name)
);
CREATE TABLE IF NOT EXISTS messages (
id TEXT PRIMARY KEY,
workspace_id TEXT NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
channel_id TEXT REFERENCES channels(id) ON DELETE CASCADE,
direct_conversation_id TEXT,
author_id TEXT NOT NULL REFERENCES users(id),
parent_message_id TEXT REFERENCES messages(id) ON DELETE CASCADE,
thread_root_id TEXT NOT NULL,
channel_seq INTEGER,
thread_seq INTEGER,
body TEXT NOT NULL,
body_format TEXT NOT NULL,
created_at TEXT NOT NULL,
edited_at TEXT,
deleted_at TEXT
);
CREATE INDEX IF NOT EXISTS idx_messages_channel_seq ON messages(channel_id, channel_seq);
CREATE INDEX IF NOT EXISTS idx_messages_thread_seq ON messages(thread_root_id, thread_seq);
CREATE INDEX IF NOT EXISTS idx_messages_direct_seq ON messages(direct_conversation_id, channel_seq);
CREATE VIRTUAL TABLE IF NOT EXISTS messages_fts USING fts5(
message_id UNINDEXED,
workspace_id UNINDEXED,
body,
tokenize = 'porter unicode61'
);
CREATE TRIGGER IF NOT EXISTS messages_fts_ai AFTER INSERT ON messages BEGIN
INSERT INTO messages_fts(message_id, workspace_id, body) VALUES (new.id, new.workspace_id, new.body);
END;
CREATE TRIGGER IF NOT EXISTS messages_fts_ad AFTER DELETE ON messages BEGIN
DELETE FROM messages_fts WHERE message_id = old.id;
END;
CREATE TRIGGER IF NOT EXISTS messages_fts_au AFTER UPDATE OF body ON messages BEGIN
DELETE FROM messages_fts WHERE message_id = old.id;
INSERT INTO messages_fts(message_id, workspace_id, body) VALUES (new.id, new.workspace_id, new.body);
END;
CREATE TABLE IF NOT EXISTS thread_state (
root_message_id TEXT PRIMARY KEY REFERENCES messages(id) ON DELETE CASCADE,
reply_count INTEGER NOT NULL DEFAULT 0,
last_reply_at TEXT,
last_reply_author_ids_json TEXT NOT NULL DEFAULT '[]'
);
CREATE TABLE IF NOT EXISTS reactions (
message_id TEXT NOT NULL REFERENCES messages(id) ON DELETE CASCADE,
user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
emoji TEXT NOT NULL,
created_at TEXT NOT NULL,
PRIMARY KEY (message_id, user_id, emoji)
);
CREATE TABLE IF NOT EXISTS events (
id TEXT PRIMARY KEY,
cursor TEXT NOT NULL UNIQUE,
workspace_id TEXT NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
channel_id TEXT,
type TEXT NOT NULL,
seq INTEGER,
payload_json TEXT NOT NULL,
created_at TEXT NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_events_workspace_cursor ON events(workspace_id, cursor);
CREATE TABLE IF NOT EXISTS uploads (
id TEXT PRIMARY KEY,
workspace_id TEXT NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
owner_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
filename TEXT NOT NULL,
content_type TEXT NOT NULL,
byte_size INTEGER NOT NULL,
storage_path TEXT NOT NULL,
created_at TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS message_attachments (
message_id TEXT NOT NULL REFERENCES messages(id) ON DELETE CASCADE,
upload_id TEXT NOT NULL REFERENCES uploads(id) ON DELETE CASCADE,
created_at TEXT NOT NULL,
PRIMARY KEY (message_id, upload_id)
);
CREATE TABLE IF NOT EXISTS direct_conversations (
id TEXT PRIMARY KEY,
workspace_id TEXT NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
created_at TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS direct_conversation_members (
conversation_id TEXT NOT NULL REFERENCES direct_conversations(id) ON DELETE CASCADE,
user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
created_at TEXT NOT NULL,
PRIMARY KEY (conversation_id, user_id)
);
CREATE TABLE IF NOT EXISTS invites (
id TEXT PRIMARY KEY,
workspace_id TEXT NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
token TEXT NOT NULL UNIQUE,
created_by TEXT NOT NULL REFERENCES users(id),
created_at TEXT NOT NULL,
accepted_at TEXT
);