162 lines
6.5 KiB
PL/PgSQL
162 lines
6.5 KiB
PL/PgSQL
-- 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; |