-- af_collab contains all the collabs. CREATE TABLE IF NOT EXISTS af_collab( oid TEXT PRIMARY KEY, owner_uid BIGINT NOT NULL, workspace_id UUID NOT NULL REFERENCES af_workspace(workspace_id) ON DELETE CASCADE, -- 0: Private, 1: Shared access_level INTEGER NOT NULL DEFAULT 0, deleted_at TIMESTAMP WITH TIME ZONE DEFAULT NULL, created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP ); CREATE UNIQUE INDEX idx_af_collab_oid ON af_collab (oid); -- collab update table. CREATE TABLE IF NOT EXISTS af_collab_update ( oid TEXT REFERENCES af_collab(oid) ON DELETE CASCADE, blob BYTEA NOT NULL, len INTEGER, partition_key INTEGER NOT NULL, md5 TEXT DEFAULT '', did TEXT DEFAULT '', encrypt INTEGER DEFAULT 0, created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, workspace_id UUID NOT NULL REFERENCES af_workspace(workspace_id) ON DELETE CASCADE, PRIMARY KEY (oid, partition_key) ) PARTITION BY LIST (partition_key); CREATE TABLE af_collab_update_document PARTITION OF af_collab_update FOR VALUES IN (0); CREATE TABLE af_collab_update_database PARTITION OF af_collab_update FOR VALUES IN (1); CREATE TABLE af_collab_update_w_database PARTITION OF af_collab_update FOR VALUES IN (2); CREATE TABLE af_collab_update_folder PARTITION OF af_collab_update FOR VALUES IN (3); CREATE TABLE af_collab_update_database_row PARTITION OF af_collab_update FOR VALUES IN (4); CREATE TABLE af_collab_update_user_awareness PARTITION OF af_collab_update FOR VALUES IN (5); -- This trigger is fired before an insert operation on the af_collab_update table. It checks if a corresponding collab -- exists in the af_collab table. If not, it creates one with the oid, uid, and current timestamp. It might cause a -- performance issue if the af_collab_update table is updated very frequently, especially if the af_collab table is large -- and if the oid column isn't indexed CREATE OR REPLACE FUNCTION insert_into_af_collab_if_not_exists() RETURNS TRIGGER AS $$ BEGIN IF NOT EXISTS ( SELECT 1 FROM af_collab WHERE oid = NEW.oid ) THEN INSERT INTO af_collab (oid, owner_uid, workspace_id, created_at) VALUES ( NEW.oid, NEW.uid, NEW.workspace_id, CURRENT_TIMESTAMP ); END IF; RETURN NEW; END; $$ LANGUAGE plpgsql; CREATE TRIGGER insert_into_af_collab_trigger BEFORE INSERT ON af_collab_update FOR EACH ROW EXECUTE FUNCTION insert_into_af_collab_if_not_exists(); CREATE TABLE af_collab_member ( uid BIGINT REFERENCES af_user(uid) ON DELETE CASCADE, oid TEXT REFERENCES af_collab(oid) ON DELETE CASCADE, role_id INTEGER REFERENCES af_roles(id), PRIMARY KEY(uid, oid) ); -- This trigger is fired after an insert operation on the af_collab table. It automatically adds the collab's owner -- to the af_collab_member table with the role 'Owner'. CREATE OR REPLACE FUNCTION insert_into_af_collab_member() RETURNS TRIGGER AS $$ BEGIN INSERT INTO af_collab_member (oid, uid, role_id) VALUES ( NEW.oid, NEW.owner_uid, ( SELECT id FROM af_roles WHERE name = 'Owner' ) ); RETURN NEW; END; $$ LANGUAGE plpgsql; CREATE TRIGGER insert_into_af_collab_member_trigger AFTER INSERT ON af_collab FOR EACH ROW EXECUTE FUNCTION insert_into_af_collab_member(); -- collab statistics. It will be used to store the edit_count of the collab. CREATE TABLE IF NOT EXISTS af_collab_statistics ( oid TEXT PRIMARY KEY, edit_count BIGINT NOT NULL DEFAULT 0 ); -- This trigger is fired after an insert operation on the af_collab_update table. It increments the edit_count of the -- corresponding collab in the af_collab_statistics table. If the collab doesn't exist in the af_collab_statistics table, -- it creates one with edit_count set to 1. CREATE OR REPLACE FUNCTION increment_af_collab_edit_count() RETURNS TRIGGER AS $$BEGIN IF EXISTS( SELECT 1 FROM af_collab_statistics WHERE oid = NEW.oid ) THEN UPDATE af_collab_statistics SET edit_count = edit_count + 1 WHERE oid = NEW.oid; ELSE INSERT INTO af_collab_statistics (oid, edit_count) VALUES (NEW.oid, 1); END IF; RETURN NEW; END; $$LANGUAGE plpgsql; CREATE TRIGGER af_collab_update_edit_count_trigger AFTER INSERT ON af_collab_update FOR EACH ROW EXECUTE FUNCTION increment_af_collab_edit_count(); -- collab snapshot. It will be used to store the snapshots of the collab. CREATE TABLE IF NOT EXISTS af_collab_snapshot ( sid BIGSERIAL PRIMARY KEY, oid TEXT NOT NULL, name TEXT DEFAULT '', blob BYTEA NOT NULL, len INTEGER NOT NULL, edit_count BIGINT NOT NULL DEFAULT 0, encrypt INTEGER DEFAULT 0, created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP ); -- This trigger is fired after an insert operation on the af_collab_snapshot table. It automatically sets the edit_count -- of the new snapshot to the current edit_count of the collab in the af_collab_statistics table. CREATE OR REPLACE FUNCTION af_collab_snapshot_update_edit_count() RETURNS TRIGGER AS $$ BEGIN NEW.edit_count := COALESCE( ( SELECT af_collab_statistics.edit_count FROM af_collab_statistics WHERE af_collab_statistics.oid = NEW.oid ), -- If the row in af_collab_statistics with given oid is found, set edit_count to 0 0 ); RETURN NEW; END; $$LANGUAGE plpgsql; CREATE TRIGGER af_collab_snapshot_update_edit_count_trigger BEFORE INSERT ON af_collab_snapshot FOR EACH ROW EXECUTE FUNCTION af_collab_snapshot_update_edit_count(); -- collab state view. It will be used to get the current state of the collab. CREATE VIEW af_collab_state AS SELECT a.oid, a.created_at AS snapshot_created_at, a.edit_count AS snapshot_edit_count, b.edit_count AS current_edit_count FROM af_collab_snapshot AS a JOIN af_collab_statistics AS b ON a.oid = b.oid; -- Insert a workspace member if the user with given uid is the owner of the workspace CREATE OR REPLACE FUNCTION insert_af_workspace_member_if_owner( p_uid BIGINT, p_role_id INT, p_workspace_id UUID ) RETURNS VOID AS $$ BEGIN -- If user is the owner, proceed with the insert operation INSERT INTO af_workspace_member (uid, role_id, workspace_id) SELECT p_uid, p_role_id, p_workspace_id FROM af_workspace WHERE workspace_id = p_workspace_id AND owner_uid = p_uid; -- Check if the insert operation was successful. If not, user is not the owner of the workspace. IF NOT FOUND THEN RAISE EXCEPTION 'Unsupported operation: User is not the owner of the workspace.'; END IF; END; $$ LANGUAGE plpgsql;