fixs and move files

This commit is contained in:
2019-08-03 00:57:00 +02:00
parent 63a50dcb92
commit 7c3028eca2
60 changed files with 171 additions and 105 deletions

View File

@@ -0,0 +1,17 @@
do
$$
declare
_password text := crypt('azerty', gen_salt('bf', 8));
begin
delete from "user";
insert into "user" (username, password, blocked_at)
select
'username' || s,
_password,
case when s % 10 = 0 then now() else null end
from generate_series(1, 1000) s;
raise notice 'user fixtures done';
end;
$$;

View File

@@ -0,0 +1,21 @@
do
$$
begin
delete from citizen;
insert into citizen (name, birthday, user_id, vote_annonymous, follow_annonymous)
select
jsonb_build_object(
'first_name', 'first name' || row_number() over (),
'last_name', 'LAST NAME' || row_number() over (),
'civility', 'm'
),
now() - interval '25 years',
u.id,
row_number() over () % 3 = 0,
row_number() over () % 5 = 1
from "user" u;
raise notice 'citizen fixtures done';
end;
$$;

View File

@@ -0,0 +1,26 @@
do
$$
begin
delete from citizen_in_workgroup;
delete from workgroup;
insert into workgroup (created_by_id, name, description, annonymous, owner_id)
select
z.id,
'name' || rn,
'description' || rn,
rn % 3 = 1,
z.id
from (select *, row_number() over () rn from citizen) z;
insert into citizen_in_workgroup (citizen_id, workgroup_id)
select
z.id,
w.id
from (select *, row_number() over ()+5 % 1000 rn from citizen) z
join (select *, row_number() over () rn from workgroup) w using (rn);
raise notice 'workgroup fixtures done';
end;
$$;

View File

@@ -0,0 +1,38 @@
do
$$
declare
_tags text[] = $tags$
{
"nature", "green", "sky",
"nuclear", "oil", "black",
"love", "human", "scuirel"
}
$tags$;
begin
delete from article_relations;
delete from article;
insert into article (version_id, created_by_id, title, annonymous, content, description, tags)
select
uuid_generate_v4(),
z.id,
'title' || row_number() over (),
row_number() over () % 3 = 0,
'content' || row_number() over (),
'description' || row_number() over (),
_tags[(row_number() over () % 5):(row_number() over () % 9)]
from citizen z;
insert into article_relations (source_id, target_id, created_by_id, comment)
select
src.id,
dest.id,
src.created_by_id,
'comment' || rn
from (select *, row_number() over () rn from article, lateral generate_series(1, 5) g) src
join (select *, row_number() over () +5 rn from article) dest using (rn);
raise notice 'article fixtures done';
end;
$$;

View File

@@ -0,0 +1,38 @@
do
$$
begin
delete from article_in_title;
delete from title;
delete from constitution;
insert into constitution (version_id, created_by_id, title, annonymous)
select
uuid_generate_v4(),
z.id,
'title' || row_number() over (),
row_number() over () % 3 = 0
from citizen z;
insert into title (created_by_id, name, rank, constitution_id)
select
c.created_by_id,
'name' || row_number() over (),
row_number() over (),
c.id
from constitution c,
lateral generate_series(1, 5) g;
insert into article_in_title (created_by_id, rank, title_id, article_id, constitution_id)
select
ti.created_by_id,
row_number() over (),
ti.id,
a.id,
ti.constitution_id
from (select *, (row_number() over () % 1005) rn from title, lateral generate_series(1, 3) g) ti
join (select *, row_number() over () rn from article) a using (rn);
raise notice 'constitution fixtures done';
end;
$$;

View File

@@ -0,0 +1,30 @@
do
$$
begin
delete from follow;
insert into follow_article (citizen_id, target_id)
select
z.id,
a.id
from (select *, row_number() over () % 995 rn from citizen, lateral generate_series(1, 5)) z
join (select *, row_number() over () rn from article) a using (rn);
insert into follow_constitution (citizen_id, target_id)
select
z.id,
a.id
from (select *, row_number() over () % 995 rn from citizen, lateral generate_series(1, 5)) z
join (select *, row_number() over () rn from constitution) a using (rn);
insert into follow_citizen (citizen_id, target_id)
select
z.id,
a.id
from (select *, row_number() over () % 995 rn from citizen, lateral generate_series(1, 5)) z
join (select *, row_number() over () rn from citizen) a using (rn);
raise notice 'follow fixtures done';
end;
$$;

View File

@@ -0,0 +1,43 @@
do
$$
begin
delete from comment;
insert into comment_on_article (citizen_id, target_id, content)
select
z.id,
a.id,
'content' || (row_number() over () * g)
from (select *, row_number() over () % 995 rn from citizen, lateral generate_series(1, 5) g) z
join (select *, row_number() over () rn from article) a using (rn);
insert into comment_on_article (citizen_id, target_id, content, parent_id)
select
z.id,
a.target_id,
'content' || row_number() over () * g,
a.id
from (select *, row_number() over () % 995 rn from citizen, lateral generate_series(1, 5) g) z
join (select *, row_number() over () rn from comment_on_article) a using (rn);
insert into comment_on_article (citizen_id, target_id, content, parent_id)
select
z.id,
a.target_id,
'content' || row_number() over () * g,
a.id
from (select *, row_number() over () % 995 rn from citizen, lateral generate_series(1, 5) g) z
join (select *, row_number() over () rn from comment_on_article where parent_id is not null) a using (rn);
insert into comment_on_constitution (citizen_id, target_id, content)
select
z.id,
a.id,
'content' || row_number() over () * g
from (select *, row_number() over () % 995 rn from citizen, lateral generate_series(1, 5) g) z
join (select *, row_number() over () rn from constitution) a using (rn);
raise notice 'comment fixtures done';
end;
$$;

View File

@@ -0,0 +1,48 @@
do
$$
begin
delete from vote_for_article;
delete from vote_for_constitution;
delete from vote_for_comment_on_article;
delete from vote_for_comment_on_constitution;
insert into vote_for_article (citizen_id, target_id, note, anonymous)
select
z.id,
a.id,
(row_number() over () % 3) -1,
(row_number() over () % 3 = 1)
from (select *, row_number() over () % 995 rn, g from citizen, lateral generate_series(1, 10) g) z
join (select *, row_number() over () rn from article) a using (rn);
insert into vote_for_constitution (citizen_id, target_id, note, anonymous)
select
z.id,
a.id,
(row_number() over () % 3) -1,
(row_number() over () % 3 = 1)
from (select *, row_number() over () % 995 rn, g from citizen, lateral generate_series(1, 5) g) z
join (select *, row_number() over () rn from constitution) a using (rn);
insert into vote_for_comment_on_article (citizen_id, target_id, note, anonymous)
select
z.id,
a.id,
(row_number() over () % 3) -1,
(row_number() over () % 3 = 1)
from (select *, row_number() over () % 995 rn, g from citizen, lateral generate_series(1, 3) g) z
join (select *, row_number() over () rn from comment_on_article) a using (rn);
insert into vote_for_comment_on_constitution (citizen_id, target_id, note, anonymous)
select
z.id,
a.id,
(row_number() over () % 3) -1,
(row_number() over () % 3 = 1)
from (select *, row_number() over () % 995 rn, g from citizen, lateral generate_series(1, 2) g) z
join (select *, row_number() over () rn from comment_on_constitution) a using (rn);
raise notice 'vote fixtures done';
end;
$$;

View File

@@ -0,0 +1,18 @@
create or replace function find_article_by_id(in id uuid, out resource json) language plpgsql as
$$
declare
_id alias for id;
begin
select to_json(t)
from (
select
a.*,
find_citizen_by_id(a.created_by_id) as created_by
into resource
from article as a
where a.id = _id
) as t;
end;
$$;
-- drop function if exists find_article_by_id(uuid, out json);

View File

@@ -0,0 +1,41 @@
create or replace function find_articles(
search text default null,
direction text default 'desc',
sort text default 'created_at',
"limit" int default 50,
"offset" int default 0,
out resource json,
out total int
) language plpgsql as
$$
begin
select json_agg(t), (select count(id) from article)
into resource, total
from (
select
a.*,
find_citizen_by_id(a.created_by_id) as created_by
from article as a
where "search" is null or title ilike '%'||"search"||'%'
order by
case direction when 'asc' then
case sort
when 'title' then a.title
when 'created_at' then a.created_at::text
else null
end
end,
case direction when 'desc' then
case sort
when 'title' then a.title
when 'created_at' then a.created_at::text
end
end
desc,
a.created_at desc
limit "limit" offset "offset"
) as t;
end;
$$;
-- drop function if exists find_articles(json, int, int);

View File

@@ -0,0 +1,20 @@
create or replace function find_last_article_by_version_id(in version_id uuid, out resource json) language plpgsql as
$$
declare
_version_id alias for version_id;
begin
select to_json(t)
from (
select
a.*,
find_citizen_by_id(a.created_by_id) as created_by
into resource
from article as a
where a.version_id = _version_id
order by a.version_number desc
limit 1
) as t;
end;
$$;
-- drop function if exists find_last_article_by_version_id(uuid, inout json);

View File

@@ -0,0 +1,32 @@
create or replace function upsert_article(inout resource json)
language plpgsql as
$$
declare
new_id uuid;
begin
insert into article (version_id, created_by_id, title, annonymous, content, description, tags)
select
coalesce(version_id, uuid_generate_v4()),
(resource#>>'{created_by, id}')::uuid,
title,
annonymous,
content,
description,
tags
from json_populate_record(null::article, resource)
returning id into new_id;
if resource->>'relations' is not null then
insert into article_relations (source_id, target_id, created_by_id)
select
(resource->>'id')::uuid,
id,
(resource#>>'{created_by, id}')::uuid
from json_populate_recordset(null::article, resource->>'relations');
end if;
select find_article_by_id(new_id) into resource;
end;
$$;
-- drop procedure if exists upsert_article(inout json);

View File

@@ -0,0 +1,16 @@
create or replace function find_citizen_by_id(in id uuid, out resource json) language plpgsql as
$$
declare
_id alias for id;
begin
select to_json(t) into resource
from (
select
z.*
from citizen as z
where z.id = _id
) as t;
end;
$$;
-- drop function if exists find_citizen_by_id(uuid, inout json);

View File

@@ -0,0 +1,17 @@
create or replace function find_citizen_by_user_id(in user_id uuid, out resource json) language plpgsql as
$$
declare
_user_id alias for user_id;
begin
select to_json(t) into resource
from (
select
z.*,
find_user_by_id(z.user_id) as "user"
from citizen as z
where z.user_id = _user_id
) as t;
end;
$$;
-- drop function if exists find_citizen_by_user_id(uuid, inout json);

View File

@@ -0,0 +1,28 @@
create or replace function upsert_citizen(inout resource json)
language plpgsql as
$$
declare
new_id uuid;
begin
insert into citizen (id, name, birthday, user_id, vote_annonymous, follow_annonymous)
select
coalesce(id, uuid_generate_v4()),
name,
birthday,
(resource#>>'{user, id}')::uuid,
coalesce(vote_annonymous, true),
coalesce(follow_annonymous, true)
from json_populate_record(null::citizen, resource)
on conflict (id) do update set
name = excluded.name,
birthday = excluded.birthday,
user_id = excluded.user_id,
vote_annonymous = excluded.vote_annonymous,
follow_annonymous = excluded.follow_annonymous
returning id into new_id;
select find_citizen_by_id(new_id) into resource;
end;
$$;
-- drop function if exists upsert_citizen(inout json);

View File

@@ -0,0 +1,25 @@
create or replace function comment(reference regclass, target_id uuid, citizen_id uuid, content text, parent_id uuid default null, out id uuid)
language plpgsql as
$$
declare
_citizen_id alias for citizen_id;
_target_id alias for target_id;
_content alias for content;
_parent_id alias for parent_id;
_id alias for id;
begin
if reference = 'article'::regclass then
insert into comment_on_article (citizen_id, target_id, content, parent_id)
values (_citizen_id, _target_id, _content, _parent_id)
returning comment_on_article.id into _id;
elseif reference = 'constitution'::regclass then
insert into comment_on_constitution (citizen_id, target_id, content, parent_id)
values (_citizen_id, _target_id, _content, _parent_id)
returning comment_on_constitution.id into _id;
else
raise exception '% no implemented', reference::text;
end if;
end;
$$;
-- drop function if exists comment(regclass, uuid, uuid, text, uuid);

View File

@@ -0,0 +1,20 @@
create or replace function edit_comment(reference regclass, id uuid, content text) returns void
language plpgsql as
$$
declare
_id alias for id;
_content alias for content;
begin
if reference = 'article'::regclass then
update comment_on_article c set
content = _content
where c.id = _id;
elseif reference = 'constitution'::regclass then
update comment_on_constitution c set
content = _content
where c.id = _id;
end if;
end;
$$;
-- drop function if exists edit_comment(regclass, uuid, uuid, text, uuid);

View File

@@ -0,0 +1,35 @@
create or replace function create_title_in_constitution(title json, constitution_id uuid default null, out resource json)
language plpgsql as
$$
declare
_title alias for title;
_constitution_id uuid = coalesce(constitution_id, (title#>>'{constitution_id}')::uuid);
_author_id uuid = (title#>>'{created_by, id}')::uuid;
new_id uuid;
begin
insert into title (created_by_id, name, rank, constitution_id)
select
_author_id,
ti.name,
row_number() OVER (),
_constitution_id
from json_populate_record(null::title, _title) ti
returning id into new_id;
if (_title->'articles' is not null) then
insert into article_in_title (created_by_id, rank, title_id, article_id, constitution_id)
select
_author_id,
row_number() over (),
new_id,
id,
coalesce ((_title->>'constitution_id')::uuid, _constitution_id)
from json_populate_recordset(null::article, _title->'articles') ;
end if;
select find_constitution_title_by_id(new_id)
into resource;
end;
$$;
-- drop function if exists create_title_in_constitution(out json);

View File

@@ -0,0 +1,19 @@
create or replace function find_constitution_by_id(in id uuid, out resource json) language plpgsql as
$$
declare
_id alias for id;
begin
select to_json(t)
from (
select
c.*,
find_citizen_by_id(c.created_by_id) as created_by,
find_constitution_titles_by_id(c.id) as titles
into resource
from constitution as c
where c.id = _id
) as t;
end;
$$;
-- drop function if exists find_constitution_by_id(uuid, out json);

View File

@@ -0,0 +1,24 @@
create or replace function find_constitution_title_by_id(in id uuid, out resource json) language plpgsql as
$$
declare
_id alias for id;
begin
select to_json(t)
from (
select
ti.id,
ti.name,
ti.rank,
array_agg(a order by ait.rank) as articles
into resource
from title as ti
left join article_in_title ait on ti.id = ait.title_id
left join article a on ait.article_id = a.id
where ti.id = _id
group by ti.id
order by ti.rank
) as t;
end;
$$;
-- drop function if exists find_constitution_title_by_id(uuid, out json);

View File

@@ -0,0 +1,20 @@
create or replace function find_constitution_titles_by_id(in constitution_id uuid, out resource json) language plpgsql as
$$
declare
_constitution_id alias for constitution_id;
begin
select json_agg(t)
from (
select
ti.id,
ti.name,
ti.rank
into resource
from title as ti
where ti.constitution_id = _constitution_id
order by ti.rank
) as t;
end;
$$;
-- drop function if exists find_constitution_titles_by_id(uuid, out json);

View File

@@ -0,0 +1,33 @@
create or replace procedure upsert_constitution(inout resource json)
language plpgsql as
$$
declare
titles json;
_title json;
_citizen_id uuid = (resource#>>'{created_by, id}')::uuid;
new_id uuid;
begin
insert into constitution (version_id, created_by_id, title, annonymous)
select
version_id,
_citizen_id,
title,
annonymous
from json_populate_record(null::constitution, resource)
returning id into new_id;
titles := (resource->>'titles');
for _title in select json_array_elements(titles) loop
if _title#>>'{created_by, id}' is null then
_title := jsonb_set(_title::jsonb, '{created_by}'::text[], jsonb_build_object('id', _citizen_id::text), true)::json;
end if;
perform create_title_in_constitution(_title, new_id);
end loop;
select find_constitution_by_id(new_id) into resource;
end;
$$;
-- drop procedure if exists upsert_constitution(inout json);

View File

@@ -0,0 +1,23 @@
create or replace function follow(reference regclass, _target_id uuid, _citizen_id uuid) returns void
language plpgsql as
$$
begin
if reference = 'article'::regclass then
insert into follow_article (citizen_id, target_id)
values (_citizen_id, _target_id)
on conflict (citizen_id, target_id) do nothing;
elseif reference = 'constitution'::regclass then
insert into follow_constitution (citizen_id, target_id)
values (_citizen_id, _target_id)
on conflict (citizen_id, target_id) do nothing;
elseif reference = 'citizen'::regclass then
insert into follow_citizen (citizen_id, target_id)
values (_citizen_id, _target_id)
on conflict (citizen_id, target_id) do nothing;
else
raise exception '% no implemented', reference::text;
end if;
end;
$$;
-- drop function if exists follow(regclass, uuid, uuid);

View File

@@ -0,0 +1,16 @@
create or replace function unfollow(reference regclass, target_id uuid, citizen_id uuid) returns void
language plpgsql as
$$
declare
_citizen_id alias for citizen_id;
_target_id alias for target_id;
begin
delete
from follow f
where f.citizen_id = _citizen_id
and f.target_id = _target_id
and f.target_reference = reference;
end;
$$;
-- drop function if exists unfollow(regclass, uuid, uuid);

View File

@@ -0,0 +1,7 @@
CREATE OR REPLACE FUNCTION random_between(low INT ,high INT)
RETURNS INT AS
$$
BEGIN
RETURN floor(random()* (high-low + 1) + low);
END;
$$ language 'plpgsql' STRICT;

View File

@@ -0,0 +1,18 @@
create or replace function check_user(in username text, in plain_password text, out resource json) language plpgsql as
$$
declare
_username alias for username;
begin
select
case when count(u) = 1
then to_jsonb(u) - 'password'
else null end
into resource
from "user" as u
where u.username = lower(_username)
and u.password = crypt(plain_password, u.password)
group by u;
end;
$$;
-- drop function if exists check_user(text, text, out json);

View File

@@ -0,0 +1,12 @@
create or replace function find_user_by_id(in id uuid, out resource json) language plpgsql as
$$
declare
_id alias for id;
begin
select to_jsonb(u) - 'password' into resource
from "user" as u
where u.id = _id;
end;
$$;
-- drop function if exists find_user_by_id(uuid, out json);

View File

@@ -0,0 +1,12 @@
create or replace function find_user_by_username(in username text, out resource json) language plpgsql as
$$
declare
_username alias for username;
begin
select to_jsonb(u) - 'password' into resource
from "user" as u
where u.username = _username;
end;
$$;
-- drop function if exists find_user_by_username(text, out json);

View File

@@ -0,0 +1,19 @@
create or replace function insert_user(inout resource json) language plpgsql as
$$
declare
new_id uuid;
begin
insert into "user" (id, username, password, blocked_at)
select
coalesce(t.id, uuid_generate_v4()),
t.username,
crypt(resource->>'plain_password', gen_salt('bf', 8)),
case when t.blocked_at is not null then now() else null end
from json_populate_record(null::"user", resource) t
returning id into new_id;
select find_user_by_id(new_id) into resource;
end;
$$;
-- drop function if exists insert_user(inout json);

View File

@@ -0,0 +1,35 @@
create or replace function vote(reference regclass, _target_id uuid, _citizen_id uuid, _note int, _anonymous bool default true) returns void
language plpgsql as
$$
begin
if reference = 'article'::regclass then
insert into vote_for_article (citizen_id, target_id, note, anonymous)
values (_citizen_id, _target_id, _note, _anonymous)
on conflict (citizen_id, target_id) do update set
note = excluded.note,
anonymous = excluded.anonymous;
elseif reference = 'constitution'::regclass then
insert into vote_for_constitution (citizen_id, target_id, note, anonymous)
values (_citizen_id, _target_id, _note, _anonymous)
on conflict (citizen_id, target_id) do update set
note = excluded.note,
anonymous = excluded.anonymous;
elseif reference = 'comment_on_article'::regclass then
insert into vote_for_comment_on_article (citizen_id, target_id, note, anonymous)
values (_citizen_id, _target_id, _note, _anonymous)
on conflict (citizen_id, target_id) do update set
note = excluded.note,
anonymous = excluded.anonymous;
elseif reference = 'comment_on_constitution'::regclass then
insert into vote_for_comment_on_constitution (citizen_id, target_id, note, anonymous)
values (_citizen_id, _target_id, _note, _anonymous)
on conflict (citizen_id, target_id) do update set
note = excluded.note,
anonymous = excluded.anonymous;
else
raise exception '% no implemented', reference::text;
end if;
end;
$$;
-- drop function if exists vote(regclass,uuid,uuid,integer,boolean);

View File

@@ -0,0 +1,42 @@
-- Stats
drop table if exists resource_view;
-- Extra resources
drop table if exists follow_article;
drop table if exists follow_constitution;
drop table if exists follow_citizen;
drop table if exists follow;
drop table if exists vote_for_article;
drop table if exists vote_for_constitution;
drop table if exists vote_for_comment_on_article;
drop table if exists vote_for_comment_on_constitution;
drop table if exists vote;
drop table if exists comment_on_article;
drop table if exists comment_on_constitution;
drop table if exists comment;
drop table if exists extra;
-- Article & Contitution
drop table if exists article_relations;
drop trigger if exists set_constitution_link_trigger on article_on_title;
drop table if exists article_in_title;
drop table if exists title;
drop function if exists set_constitution_link();
drop trigger if exists generate_version_number_trigger on article;
drop table if exists article;
drop function if exists generate_version_number(regclass, uuid);
drop trigger if exists generate_version_number_trigger on constitution;
drop table if exists constitution;
drop function if exists set_version_number();
-- User
drop table if exists moderator;
drop table if exists citizen_in_workgroup;
drop table if exists workgroup;
drop table if exists citizen;
drop table if exists "user";
drop type if exists public."name";

View File

@@ -0,0 +1,310 @@
-- Users
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_id uuid not null references workgroup (id),
created_at timestamptz default now() not null,
primary key (citizen_id, workgroup_id)
);
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 desc
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 desc
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),
comment text null,
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),
unique (citizen_id, target_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),
unique (citizen_id, target_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),
unique (citizen_id, target_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),
unique (citizen_id, target_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),
unique (citizen_id, target_id)
) inherits (extra);
create table vote_for_article
(
target_reference regclass default 'article'::regclass not null,
foreign key (target_id) references article (id),
foreign key (citizen_id) references citizen (id),
primary key (id),
unique (citizen_id, target_id)
) inherits (vote);
create table vote_for_constitution
(
target_reference regclass default 'constitution'::regclass not null,
foreign key (target_id) references constitution (id),
foreign key (citizen_id) references citizen (id),
primary key (id),
unique (citizen_id, target_id)
) inherits (vote);
create table vote_for_comment_on_article
(
target_reference regclass default 'comment_on_article'::regclass not null,
foreign key (target_id) references comment_on_article (id),
foreign key (citizen_id) references citizen (id),
primary key (id),
unique (citizen_id, target_id)
) inherits (vote);
create table vote_for_comment_on_constitution
(
target_reference regclass default 'comment_on_constitution'::regclass not null,
foreign key (target_id) references comment_on_constitution (id),
foreign key (citizen_id) references citizen (id),
primary key (id),
unique (citizen_id, target_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
);

View File

@@ -0,0 +1,53 @@
do
$$
declare
created_user json := '{"username": "george", "plain_password": "azerty"}';
_user_id uuid;
_citizen_id uuid;
created_citizen json := '{"name": {"first_name":"George", "last_name":"MICHEL"}, "birthday": "2001-01-01"}';
created_article json := '{"version_id":"933b6a1b-50c9-42b6-989f-c02a57814ef9", "title": "Love the world", "annonymous": false, "content": "bla bal bla", "tags": ["love", "test"]}';
selected_article json;
begin
-- insert user for context
select insert_user(created_user) into created_user;
_user_id := created_user->>'id';
created_citizen := jsonb_set(created_citizen::jsonb, '{user}'::text[], jsonb_build_object('id', _user_id::text), true)::json;
assert created_citizen#>>'{user, id}' = _user_id::text, format('userId in citizen must be the same as user, %s = %s', created_citizen#>>'{user, id}', _user_id::text);
-- insert new citizen for context
call upsert_citizen(created_citizen);
_citizen_id := created_citizen->>'id';
created_article := jsonb_set(created_article::jsonb, '{created_by}'::text[], jsonb_build_object('id', _citizen_id::text), true)::json;
assert created_article#>>'{created_by, id}' = _citizen_id::text, format('citizenId in article must be the same as citizen, %s != %s', created_article#>>'{created_by, id}', _citizen_id::text);
-- upsert article
call upsert_article(created_article);
assert created_article->>'version_id' is not null, 'version_id should not be null';
assert (created_article->>'version_number')::int = 1, format('version_number must be equal to 1, %s instead', created_article->>'version_number');
-- try tu create new version
call upsert_article(created_article);
assert (created_article->>'version_number')::int = 2, format('version_number must be equal to 2, %s instead', created_article->>'version_number');
-- get article by id and check the title
select find_article_by_id((created_article->>'id')::uuid) into selected_article;
assert selected_article->>'title' = 'Love the world', format('title must be "Love the world", %s', selected_article->>'title');
-- get article by version_id and check the title
select find_last_article_by_version_id((created_article->>'version_id')::uuid) into selected_article;
assert selected_article->>'title' = 'Love the world', format('title must be "Love the world", %s', selected_article->>'title');
assert (selected_article->>'version_number')::int = 2, format('version_id must be 2, %s instead', selected_article->>'version_number');
-- check if user id is returned
assert (selected_article#>>'{created_by, user, id}')::uuid = _user_id, format('user_id must be %s instead of %s', _user_id, (selected_article#>>'{created_by, user, id}')::uuid);
-- delete article and context
delete from article;
delete from citizen;
delete from "user";
-- check if find by id return null if article not exist
select find_citizen_by_user_id((created_citizen->>'id')::uuid) into selected_article;
assert selected_article is null, format('article must be null if not exist, %s', selected_article);
raise notice 'article test pass';
end;
$$;

View File

@@ -0,0 +1,46 @@
do
$$
declare
wrong_citizen json;
created_user json := '{"username": "george", "plain_password": "azerty"}';
_user_id uuid;
created_citizen json := '{"name": {"first_name":"George", "last_name":"MICHEL"}, "birthday": "2001-01-01"}';
selected_citizen json;
begin
-- insert user for context
select insert_user(created_user) into created_user;
_user_id := created_user->>'id';
created_citizen := jsonb_set(created_citizen::jsonb, '{user}'::text[], jsonb_build_object('id', _user_id::text), true)::json;
assert created_citizen#>>'{user, id}' = _user_id::text, format('userId in citizen must be the same as user, %s = %s', created_citizen#>>'{user, id}', _user_id::text);
-- insert new citizen
call upsert_citizen(created_citizen);
assert created_citizen->>'birthday' = '2001-01-01'::text, format('birthday of inserted citizen must be the same of the original object, %s != %s', created_citizen->>'birthday', '2001-01-01'::text);
-- insert citizen without first name and test if throw exception
wrong_citizen := (created_citizen::jsonb - '{name, first_name}'::text[])::json;
begin
call upsert_citizen(wrong_citizen);
assert false, 'upsert_citizen must be throw exception if first_name not exist';
exception when not_null_violation then
end;
-- get citizen by id and check the first name
select find_citizen_by_id((created_citizen->>'id')::uuid) into selected_citizen;
assert selected_citizen#>>'{name, first_name}' = 'George', format('first name must be George, %s', selected_citizen#>>'{name, first_name}');
-- get citizen by user id and check the first name
select find_citizen_by_user_id((created_citizen->>'user_id')::uuid) into selected_citizen;
assert selected_citizen#>>'{name, first_name}' = 'George', format('first name must be George, %s', selected_citizen#>>'{name, first_name}');
-- delete citizen
delete from citizen where user_id = _user_id;
delete from "user" where username = 'george';
-- check if fint by id return null if citizen not exist
select find_citizen_by_user_id((created_citizen->>'user_id')::uuid) into selected_citizen;
assert selected_citizen is null, format('citizen must be null if not exist, %s', selected_citizen);
raise notice 'citizen test pass';
end;
$$;

View File

@@ -0,0 +1,71 @@
do
$$
declare
created_user json := '{"username": "george", "plain_password": "azerty"}';
created_user2 json := '{"username": "john", "plain_password": "qwerty"}';
_citizen_id uuid;
created_citizen json := $json$
{
"name": {
"first_name": "George",
"last_name": "MICHEL"
},
"birthday": "2001-01-01"
}
$json$;
created_article json := $json$
{
"version_id": "933b6a1b-50c9-42b6-989f-c02a57814ef9",
"title": "Love the world",
"annonymous": false,
"content": "bla bal bla",
"tags": [
"love",
"test"
]
}
$json$;
_comment_id uuid;
begin
-- insert user for context
select insert_user(created_user) into created_user;
select insert_user(created_user2) into created_user2;
created_citizen := jsonb_set(created_citizen::jsonb, '{user}'::text[], jsonb_build_object('id', created_user->>'id'), true)::json;
-- insert new citizen for context
call upsert_citizen(created_citizen);
_citizen_id := created_citizen->>'id';
created_article := jsonb_set(created_article::jsonb, '{created_by}'::text[], jsonb_build_object('id', _citizen_id::text), true)::json;
assert created_article#>>'{created_by, id}' = _citizen_id::text, format('citizenId in article must be the same as citizen, %s != %s', created_article#>>'{created_by, id}', _citizen_id::text);
-- upsert article
call upsert_article(created_article);
select comment(
reference => 'article'::regclass,
target_id => (created_article->>'id')::uuid,
citizen_id => _citizen_id,
content => 'Ho my god !'::text
) into _comment_id;
assert (select count(*) = 1 from "comment"), 'comment must be inserted';
perform edit_comment(
reference => 'article'::regclass,
id => _comment_id,
content => 'edited'::text
);
assert (select count(*) = 1 from "comment"), 'edit comment must not insert new comment';
assert (select count(*) = 1 from "comment" where content = 'edited'), 'edit comment must not insert new comment';
-- delete comment and context
delete from "comment";
delete from article;
delete from citizen;
delete from "user";
raise notice 'comment test pass';
end;
$$;
-- select uuid_generate_v4();

View File

@@ -0,0 +1,81 @@
do
$$
declare
created_user json := '{"username": "george", "plain_password": "azerty"}';
_user_id uuid;
_citizen_id uuid;
created_citizen json := $json$
{
"name": {
"first_name": "George",
"last_name": "MICHEL"
},
"birthday": "2001-01-01"
}
$json$;
created_article json := $json$
{
"version_id": "933b6a1b-50c9-42b6-989f-c02a57814ef9",
"title": "Love the world",
"annonymous": false,
"content": "bla bal bla",
"tags": [
"love",
"test"
]
}
$json$;
created_constitution json := $json$
{
"version_id": "18ff6dd6-3bc1-4c59-82f0-5e2a8d54ae3e",
"title": "Love the world",
"annonymous": false,
"titles": [
{
"name": "titleOne"
},
{
"name": "titleTwo"
}
]
}
$json$;
begin
-- insert user for context
select insert_user(created_user) into created_user;
_user_id := created_user->>'id';
created_citizen := jsonb_set(created_citizen::jsonb, '{user}'::text[], jsonb_build_object('id', _user_id::text), true)::json;
assert created_citizen#>>'{user, id}' = _user_id::text, format('userId in citizen must be the same as user, %s = %s', created_citizen#>>'{user, id}', _user_id::text);
-- insert new citizen for context
call upsert_citizen(created_citizen);
_citizen_id := created_citizen->>'id';
created_article := jsonb_set(created_article::jsonb, '{created_by}'::text[], jsonb_build_object('id', _citizen_id::text), true)::json;
assert created_article#>>'{created_by, id}' = _citizen_id::text, format('citizenId in article must be the same as citizen, %s != %s', created_article#>>'{created_by, id}', _citizen_id::text);
-- upsert article for context
call upsert_article(created_article);
assert created_article->>'version_id' is not null, 'version_id should not be null';
-- create new constitution
created_constitution := jsonb_set(created_constitution::jsonb, '{created_by}'::text[], jsonb_build_object('id', _citizen_id::text), true)::json;
created_constitution := jsonb_set(created_constitution::jsonb, '{titles, 0, articles}'::text[], jsonb_build_array(jsonb_build_object('id', created_article->>'id')), true)::json;
call upsert_constitution(created_constitution);
assert (created_constitution->>'version_number')::int = 1, format('version_number must be equal to 1, %s instead', created_constitution->>'version_number');
assert created_constitution#>>'{titles, 0, name}' = 'titleOne'::text, format('the name of the first title of contitution must be %s, not %s', 'titleOne', created_constitution#>>'{titles, 0, name}');
-- delete article and context
delete from article_in_title;
delete from title;
delete from constitution;
delete from article;
delete from citizen;
delete from "user";
raise notice 'constitution test pass';
end;
$$;
-- select uuid_generate_v4();

View File

@@ -0,0 +1,59 @@
do
$$
declare
created_user json := '{"username": "george", "plain_password": "azerty"}';
created_user2 json := '{"username": "john", "plain_password": "qwerty"}';
_citizen_id uuid;
_citizen_id2 uuid;
created_citizen json := $json$
{
"name": {
"first_name": "George",
"last_name": "MICHEL"
},
"birthday": "2001-01-01"
}
$json$;
created_citizen2 json := $json$
{
"name": {
"first_name": "John",
"last_name": "Doe"
},
"birthday": "2002-01-01"
}
$json$;
begin
-- insert user for context
select insert_user(created_user) into created_user;
select insert_user(created_user2) into created_user2;
created_citizen := jsonb_set(created_citizen::jsonb, '{user}'::text[], jsonb_build_object('id', created_user->>'id'), true)::json;
created_citizen2 := jsonb_set(created_citizen2::jsonb, '{user}'::text[], jsonb_build_object('id', created_user2->>'id'), true)::json;
-- insert new citizen for context
call upsert_citizen(created_citizen);
_citizen_id := created_citizen->>'id';
-- insert new citizen for context
call upsert_citizen(created_citizen2);
_citizen_id2 := created_citizen2->>'id';
perform follow('citizen'::regclass, _citizen_id, _citizen_id2);
assert (select count(*) > 0 from follow), 'follow must be inserted';
perform follow('citizen'::regclass, _citizen_id, _citizen_id2);
assert (select count(*) > 0 from follow), 'follow must be inserted';
perform unfollow('citizen'::regclass, _citizen_id, _citizen_id2);
assert (select count(*) = 0 from follow), 'follow must be deleted after unfollow';
-- delete follow and context
delete from citizen;
delete from "user";
raise notice 'follow test pass';
end;
$$;
-- select uuid_generate_v4();

View File

@@ -0,0 +1,35 @@
do
$$
declare
created_user json := '{"username": "george", "plain_password": "azerty"}';
selected_user json;
exist_user json;
begin
-- Insert user and check if username and password is correct
select insert_user(created_user) into created_user;
assert created_user->>'username' = 'george', 'username must be george';
assert created_user->>'password' is null, 'password must not be returned';
-- get user by there id and check the username is correct
select find_user_by_id((created_user->>'id')::uuid) into selected_user;
assert selected_user->>'username' = 'george', format('username must be george, %s instead', selected_user);
-- get user by username and check the username is correct
select find_user_by_username(created_user->>'username') into selected_user;
assert selected_user->>'username' = 'george', 'username must be george';
-- check if user exist with username and password and verify the reterned user
select check_user('george', 'azerty') into exist_user;
assert exist_user is not null, format('the function check_user must be return user object if username and password is correct, %s is return', exist_user::text);
assert exist_user->>'username' = 'george', format('the function check_user must be return user object with username is "george", %s is return', exist_user::text);
assert exist_user->>'password' is null, format('the function check_user must not be return the password, %s is return', exist_user::text);
-- delete user and check if user is really not exists
delete from "user" where username = 'george';
select check_user('george', 'azerty') into exist_user;
assert exist_user is null, format('the function check_user must be return null if user not exist, %s is return', exist_user::text);
raise notice 'user test pass';
end;
$$;

View File

@@ -0,0 +1,82 @@
do
$$
declare
created_user json := '{"username": "george", "plain_password": "azerty"}';
_citizen_id uuid;
created_citizen json := $json$
{
"name": {
"first_name": "George",
"last_name": "MICHEL"
},
"birthday": "2001-01-01"
}
$json$;
created_article json := $json$
{
"version_id": "933b6a1b-50c9-42b6-989f-c02a57814ef9",
"title": "Love the world",
"annonymous": false,
"content": "bla bal bla",
"tags": [
"love",
"test"
]
}
$json$;
begin
-- insert user for context
select insert_user(created_user) into created_user;
created_citizen := jsonb_set(created_citizen::jsonb, '{user}'::text[], jsonb_build_object('id', created_user->>'id'), true)::json;
-- insert new citizen for context
call upsert_citizen(created_citizen);
_citizen_id := created_citizen->>'id';
created_article := jsonb_set(created_article::jsonb, '{created_by}'::text[], jsonb_build_object('id', _citizen_id::text), true)::json;
assert created_article#>>'{created_by, id}' = _citizen_id::text, format('citizenId in article must be the same as citizen, %s != %s', created_article#>>'{created_by, id}', _citizen_id::text);
-- upsert article
call upsert_article(created_article);
perform vote(
reference => 'article'::regclass,
_target_id => (created_article->>'id')::uuid,
_citizen_id => _citizen_id,
_note => 1
);
assert (select count(*) = 1 from vote_for_article), 'vote must be inserted';
assert (select note = 1 from vote_for_article limit 1), 'vote must be equal to 1';
perform vote(
reference => 'article'::regclass,
_target_id => (created_article->>'id')::uuid,
_citizen_id => _citizen_id,
_note => -1
);
assert (select count(*) = 1 from vote_for_article), 'vote must be inserted';
assert (select note = -1 from vote_for_article limit 1), 'vote must be equal to -1';
begin
perform vote(
reference => 'article'::regclass,
_target_id => (created_article->>'id')::uuid,
_citizen_id => _citizen_id,
_note => -10
);
assert false, 'vote must be throw exception if note is not -1, 0 or 1';
exception when check_violation then
end;
-- delete vote and context
delete from vote;
delete from article;
delete from citizen;
delete from "user";
raise notice 'vote test pass';
end;
$$;
-- select uuid_generate_v4();