CREATE EXTENSION citext; CREATE TABLE users( id UUID NOT NULL PRIMARY KEY, handle CITEXT NOT NULL UNIQUE, password TEXT, profpic TEXT ); CREATE TABLE sessions ( id UUID NOT NULL PRIMARY KEY, token BYTEA NOT NULL UNIQUE, user_id UUID NOT NULL REFERENCES users(id), expiry TIMESTAMPTZ NOT NULL, revoked BOOLEAN NOT NULL DEFAULT FALSE, revoked_at TIMESTAMPTZ DEFAULT NULL, revoked_by UUID DEFAULT NULL REFERENCES users(id), CHECK( (revoked = FALSE AND revoked_at IS NULL AND revoked_by IS NULL) OR (revoked = TRUE AND revoked_at IS NOT NULL AND revoked_by IS NOT NULL) ) ); CREATE INDEX sessions_by_userid ON sessions(user_id); CREATE TABLE user_permissions ( user_id UUID NOT NULL REFERENCES users(id), permission TEXT NOT NULL, state BOOLEAN NOT NULL, PRIMARY KEY (user_id, permission) ); CREATE TABLE quotes ( id UUID NOT NULL PRIMARY KEY, timestamp TIMESTAMP NOT NULL, location TEXT DEFAULT NULL, context TEXT DEFAULT NULL, created_by UUID REFERENCES users(id), public BOOLEAN DEFAULT FALSE, fts TSVECTOR NOT NULL DEFAULT ''::tsvector -- TODO: trigger?? ); CREATE INDEX quotes_by_creation_user ON quotes(created_by); CREATE TABLE persons ( id UUID NOT NULL PRIMARY KEY, bio TEXT DEFAULT NULL, profpic TEXT DEFAULT NULL ); CREATE TABLE names ( id UUID NOT NULL PRIMARY KEY, name CITEXT NOT NULL, is_primary BOOLEAN NOT NULL DEFAULT FALSE, person_id UUID NOT NULL REFERENCES persons(id) ); CREATE INDEX names_by_personid ON names(person_id); CREATE UNIQUE INDEX no_name_duplicate_for_same_person ON names(person_id, name); CREATE UNIQUE INDEX primary_name_uniqueness ON names(person_id) WHERE is_primary = TRUE; CREATE TABLE lines ( id UUID NOT NULL PRIMARY KEY, quote_id UUID NOT NULL REFERENCES quotes(id), ordering SMALLINT NOT NULL, content TEXT NOT NULL ); CREATE INDEX lines_by_quoteid ON lines(quote_id); CREATE UNIQUE INDEX lines_unique_ordering ON lines(quote_id, ordering); CREATE TABLE line_authors ( line_id UUID REFERENCES lines(id), name_id UUID REFERENCES names(id), PRIMARY KEY (line_id, name_id) ); CREATE TABLE tags ( id UUID NOT NULL PRIMARY KEY, name CITEXT NOT NULL UNIQUE ); CREATE TABLE user_quote_likes ( quote_id UUID NOT NULL REFERENCES quotes(id), user_id UUID NOT NULL REFERENCES users(id), PRIMARY KEY (quote_id, user_id) ); CREATE INDEX quote_likes_by_user ON user_quote_likes(user_id); CREATE INDEX quote_likes_by_quote ON user_quote_likes(quote_id); CREATE TABLE quote_tags ( quote_id UUID NOT NULL REFERENCES quotes(id), tag_id UUID NOT NULL REFERENCES tags(id), PRIMARY KEY (quote_id, tag_id) ); CREATE INDEX quote_tags_by_quote ON quote_tags(quote_id); CREATE INDEX quote_tags_by_tag ON quote_tags(tag_id); CREATE TABLE logs ( id UUID NOT NULL PRIMARY KEY, actor UUID NOT NULL REFERENCES users(id), target UUID, actiontype TEXT NOT NULL, payload JSONB ); CREATE INDEX logs_by_actor ON logs(actor); CREATE INDEX logs_by_target ON logs(target);