From c7fb30d4ed091c37e0cc204463d40cc6b50e4a81 Mon Sep 17 00:00:00 2001 From: TMA Date: Sun, 15 Mar 2026 13:27:51 +0100 Subject: [PATCH] DB schema --- brmelect.sql | 186 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 brmelect.sql diff --git a/brmelect.sql b/brmelect.sql new file mode 100644 index 0000000..d458db8 --- /dev/null +++ b/brmelect.sql @@ -0,0 +1,186 @@ +CREATE SCHEMA IF NOT EXISTS brm; + +CREATE TABLE brm.members ( + member_id INTEGER PRIMARY KEY, + nick TEXT NOT NULL, + name TEXT NOT NULL, + surname TEXT NOT NULL +); + +CREATE OR REPLACE FUNCTION brm.ensure_member( + i_member_id INTEGER, + i_nick TEXT, + i_name TEXT, + i_surname TEXT +) +RETURNS INTEGER +LANGUAGE SQL +BEGIN ATOMIC + INSERT INTO brm.members (member_id, nick, name, surname) + VALUES (i_member_id, i_nick, i_name, i_surname) + ON CONFLICT (member_id) + DO UPDATE + SET + nick = EXCLUDED.nick, + name = EXCLUDED.name, + surname = EXCLUDED.surname + RETURNING member_id; +END; + +CREATE TABLE brm.meetings ( + meeting_id INTEGER PRIMARY KEY, + title TEXT NOT NULL, + held_on TSTZRANGE NOT NULL +); + +CREATE OR REPLACE FUNCTION brm.start_meeting( + i_meeting_id INTEGER, + i_title TEXT +) +RETURNS INTEGER +LANGUAGE SQL +BEGIN ATOMIC +INSERT INTO brm.meetings (meeting_id, title, held_on) +VALUES ( + i_meeting_id, + i_title, + CASE + WHEN now() < date_trunc('day', now()) + interval '23 hours' + THEN tstzrange( + now(), + date_trunc('day', now()) + interval '23 hours', + '[)' + ) + END +) +RETURNING meeting_id; +END; + +CREATE TABLE brm.votes ( + vote_id SERIAL PRIMARY KEY, + meeting_id INTEGER NOT NULL REFERENCES brm.meetings(meeting_id), + title TEXT NOT NULL, + open_time TSTZRANGE NOT NULL, + is_active BOOLEAN NOT NULL DEFAULT FALSE +); + +CREATE TABLE brm.meeting_member_status ( + member_id INTEGER NOT NULL REFERENCES brm.members(member_id), + meeting_id INTEGER NOT NULL REFERENCES brm.meetings(meeting_id), + in_debt BOOLEAN NOT NULL, + short_tenure BOOLEAN NOT NULL, + has_vote BOOLEAN NOT NULL, + eligible BOOLEAN NOT NULL, + present BOOLEAN NOT NULL DEFAULT FALSE, + PRIMARY KEY (member_id, meeting_id) +); + +CREATE OR REPLACE FUNCTION brm.record_meeting_member_status( + i_meeting_id INTEGER, + i_member_id INTEGER, + i_in_debt BOOLEAN, + i_short_tenure BOOLEAN, + i_has_vote BOOLEAN +) +RETURNS INTEGER +LANGUAGE SQL +BEGIN ATOMIC + INSERT INTO brm.meeting_member_status (member_id, meeting_id, in_debt, short_tenure, has_vote, eligible) + SELECT i_member_id, i_meeting_id, i_in_debt, i_short_tenure, i_has_vote, i_has_vote + RETURNING member_id; +END; + +CREATE OR REPLACE FUNCTION brm.record_current_meeting_member_status( + i_member_id INTEGER, + i_in_debt BOOLEAN, + i_short_tenure BOOLEAN, + i_has_vote BOOLEAN +) +RETURNS INTEGER +LANGUAGE SQL +BEGIN ATOMIC + SELECT brm.record_meeting_member_status((SELECT MAX(meeting_id) FROM brm.meetings), + i_member_id, i_in_debt, i_short_tenure, i_has_vote); +END; + + + +CREATE TABLE brm.vote_member_status ( + member_id INTEGER NOT NULL REFERENCES brm.members(member_id), + meeting_id INTEGER NOT NULL REFERENCES brm.meetings(meeting_id), + vote_id INTEGER NOT NULL REFERENCES brm.votes(vote_id), + in_debt BOOLEAN NOT NULL, + short_tenure BOOLEAN NOT NULL, + has_vote BOOLEAN NOT NULL, + eligible BOOLEAN NOT NULL, + present BOOLEAN NOT NULL, + PRIMARY KEY (member_id, meeting_id, vote_id) +); + +CREATE OR REPLACE FUNCTION brm.create_vote_and_init_status( + i_meeting_id INTEGER, + i_title TEXT +) +RETURNS INTEGER +LANGUAGE SQL +BEGIN ATOMIC + WITH new_vote AS ( + INSERT INTO brm.votes (meeting_id, title, open_time, is_active) + VALUES (i_meeting_id, i_title, tstzrange(now(), now()+interval '30 minutes'), TRUE) + RETURNING vote_id, meeting_id + ), + copied AS ( + INSERT INTO brm.vote_member_status ( + member_id, + meeting_id, + vote_id, + in_debt, + short_tenure, + has_vote, + eligible + ) + SELECT + m.member_id, + m.meeting_id, + v.vote_id, + m.in_debt, + m.short_tenure, + m.has_vote, + m.eligible + FROM brm.meeting_member_status m + JOIN new_vote v ON v.meeting_id = m.meeting_id + ) + SELECT vote_id FROM new_vote; +END; + +CREATE OR REPLACE FUNCTION brm.new_vote_for_current_meeting( + i_title TEXT +) +RETURNS INTEGER +LANGUAGE SQL +BEGIN ATOMIC + SELECT brm.create_vote_and_init_status((SELECT MAX(meeting_id) FROM brm.meetings), i_title); +END; + +CREATE OR REPLACE FUNCTION brm.sync_vote_present_to_meeting(i_member_id INTEGER, i_meeting_id INTEGER, i_present BOOLEAN) +RETURNS VOID +LANGUAGE SQL +BEGIN ATOMIC + UPDATE brm.meeting_member_status + SET present = i_present + WHERE member_id = i_member_id AND meeting_id = i_meeting_id; +END; + +CREATE OR REPLACE FUNCTION brm.sync_meeting_present_to_votes(i_member_id INTEGER, i_meeting_id INTEGER, i_present BOOLEAN) +RETURNS VOID +LANGUAGE SQL +BEGIN ATOMIC + UPDATE brm.vote_member_status + SET present = i_present + WHERE member_id = i_member_id + AND meeting_id = i_meeting_id + AND EXISTS (SELECT 1 FROM brm.votes WHERE meeting_id = i_meeting_id AND is_active = TRUE); +END; +``` +---------------------------------------------------------------- +-- vim: set et sw=4 ts=4 :