-- Users create extension if not exists pgcrypto; create table "user" ( id uuid default uuid_generate_v4() not null primary key, created_at timestamptz default now() not null, updated_at timestamptz default now() not null check ( updated_at >= created_at ), blocked_at timestamptz default null null, username varchar(64) not null check ( username != '' and lower(username) = username) unique, password text not null check ( password != '' ) ); create table citizen ( id uuid default uuid_generate_v4() not null primary key, created_at timestamptz default now() not null, name jsonb not null check ( name ? 'first_name' and name ? 'last_name' ), birthday date not null, user_id uuid not null references "user" (id) unique, vote_annonymous boolean default true not null, follow_annonymous boolean default true not null ); create table workgroup ( id uuid default uuid_generate_v4() not null primary key, created_at timestamptz default now() not null, updated_at timestamptz default now() not null check ( updated_at >= created_at ), created_by_id uuid not null references citizen (id), name varchar(128) not null, description text null, annonymous boolean default false not null, logo text null, owner_id uuid not null references citizen (id) ); create table citizen_in_workgroup ( citizen_id uuid not null references citizen (id), workgroup uuid not null references workgroup (id), created_at timestamptz default now() not null, primary key (citizen_id, workgroup) ); create table moderator ( id uuid default uuid_generate_v4() not null primary key, created_at timestamptz default now() not null, updated_at timestamptz default now() not null check ( updated_at >= created_at ), assigned_period tstzrange[] default '{}' not null, user_id uuid not null references "user" (id) ); -- Article & Constitution create or replace function generate_version_number(tablename regclass, version_id uuid, out generated_number int) language plpgsql as $$ declare _version_id alias for version_id; begin if (tablename = 'article'::regclass) then select version_number + 1 into generated_number from article as t where t.version_id = _version_id order by version_number limit 1; elseif tablename = 'constitution'::regclass then select version_number + 1 into generated_number from constitution as t where t.version_id = _version_id order by version_number limit 1; else raise exception '% is not implemented', tablename::text; end if; if not found then generated_number := 1; end if; end; $$; create or replace function set_version_number() returns trigger language plpgsql as $$ begin new.version_number = generate_version_number(tg_table_name::regclass, new.version_id); return new; end; $$; create table article ( id uuid default uuid_generate_v4() not null primary key, created_at timestamptz default now() not null, created_by_id uuid not null references citizen (id), version_id uuid default uuid_generate_v4() not null, version_number int not null, title text not null, annonymous boolean default false not null, content text not null check ( content != '' ), description text, tags varchar(32)[] default '{}' not null, unique (version_id, version_number) ); create trigger generate_version_number_trigger before insert on article for each row execute function set_version_number(); create table constitution ( id uuid default uuid_generate_v4() not null primary key, created_at timestamptz default now() not null, created_by_id uuid not null references citizen (id), version_id uuid default uuid_generate_v4() not null, version_number int not null, title text not null, annonymous boolean default false not null ); create trigger generate_version_number_trigger before insert on constitution for each row execute procedure set_version_number(); create table title ( id uuid default uuid_generate_v4() not null primary key, created_at timestamptz default now() not null, created_by_id uuid not null references citizen (id), name text not null check ( name != '' ), rank int not null, constitution_id uuid not null references constitution (id) ); create table article_in_title ( id uuid default uuid_generate_v4() not null primary key, created_at timestamptz default now() not null, created_by_id uuid not null references citizen (id), rank int not null, title_id uuid not null references title (id), article_id uuid not null references article (id), constitution_id uuid not null references constitution (id) ); create or replace function set_constitution_link() returns trigger language plpgsql as $$ begin new.constitution_id = ( select t.constitution_id from title as t where t.id = new.title_id ); return new; end; $$; create trigger set_constitution_link_trigger before insert on article_in_title execute procedure set_constitution_link(); create table article_relations ( source_id uuid references article, target_id uuid references article check ( source_id != target_id ), created_at timestamptz default now(), created_by_id uuid not null references citizen (id), primary key (source_id, target_id) ); -- Extra resources create table extra ( id uuid default uuid_generate_v4() not null primary key, created_at timestamptz default now() not null, citizen_id uuid not null references citizen (id), target_id uuid not null, target_reference regclass not null ); create table follow ( foreign key (citizen_id) references citizen (id), primary key (id) ) inherits (extra); create table follow_article ( target_reference regclass default 'article'::regclass not null, foreign key (citizen_id) references citizen (id), foreign key (target_id) references article (id), primary key (id) ) inherits (follow); create table follow_constitution ( target_reference regclass default 'constitution'::regclass not null, foreign key (citizen_id) references citizen (id), foreign key (target_id) references constitution (id), primary key (id) ) inherits (follow); create table follow_citizen ( target_reference regclass default 'citizen'::regclass not null, foreign key (citizen_id) references citizen (id), foreign key (target_id) references citizen (id), primary key (id) ) inherits (follow); create table comment ( updated_at timestamptz default now() not null check ( updated_at >= created_at ), "content" text not null check ( content != '' ), parent_id uuid null references comment (id), foreign key (citizen_id) references citizen (id), primary key (id) ) inherits (extra); create table comment_on_article ( target_reference regclass default 'article'::regclass not null, foreign key (citizen_id) references citizen (id), foreign key (target_id) references article (id), foreign key (parent_id) references comment_on_article (id), primary key (id) ) inherits (comment); create table comment_on_constitution ( target_reference regclass default 'constitution'::regclass not null, foreign key (citizen_id) references citizen (id), foreign key (target_id) references constitution (id), foreign key (parent_id) references comment_on_constitution (id), primary key (id) ) inherits (comment); create table vote ( anonymous boolean default true not null, note int not null check ( note >= -1 and note <= 1 ), foreign key (citizen_id) references citizen (id), primary key (id) ) inherits (extra); create table vote_for_article ( foreign key (target_id) references article (id), foreign key (citizen_id) references citizen (id), primary key (id) ) inherits (vote); create table vote_for_constitution ( foreign key (target_id) references constitution (id), foreign key (citizen_id) references citizen (id), primary key (id) ) inherits (vote); create table vote_for_comment_on_article ( foreign key (target_id) references comment_on_article (id), foreign key (citizen_id) references citizen (id), primary key (id) ) inherits (vote); create table vote_for_comment_on_constitution ( primary key (id), foreign key (target_id) references comment_on_constitution (id), foreign key (target_id) references citizen (id) ) inherits (vote); -- Stats create table resource_view ( id uuid default uuid_generate_v4() not null primary key, type regclass not null, created_at timestamptz default now() not null, created_by_id uuid null references citizen (id), ip cidr null );