Add draft for article & constitution, auto set last_version column

This commit is contained in:
2019-09-06 00:36:41 +02:00
parent d7d88a3295
commit 56ea1507f7
5 changed files with 341 additions and 166 deletions

View File

@@ -13,7 +13,7 @@ begin
delete from article_relations;
delete from article;
insert into article (id, version_id, created_by_id, title, anonymous, content, description, tags, created_at)
insert into article (id, version_id, created_by_id, title, anonymous, content, description, tags, created_at, is_draft)
select
uuid_in(md5('article'||row_number() over ())::cstring),
uuid_in(md5('article_v'||row_number() over () % (_citizen_count / 2))::cstring),
@@ -23,7 +23,8 @@ begin
'content' || row_number() over (),
'description' || row_number() over (),
_tags[(row_number() over () % 5):(row_number() over () % 9)],
now() + (row_number() over () * interval '7 minute 3 second')
now() + (row_number() over () * interval '7 minute 3 second'),
(row_number() over () % 7) = 0
from citizen z;
insert into article_relations (source_id, target_id, created_by_id, comment)

View File

@@ -11,6 +11,8 @@ begin
into resource
from article as a
where a.version_id = _version_id
and a.is_draft = false
and a.deleted_at is null
order by a.version_number desc
limit 1
) as t;

View File

@@ -27,11 +27,19 @@ drop table if exists title;
drop function if exists set_constitution_link();
drop trigger if exists generate_version_number_trigger on article;
drop trigger if exists set_to_last_version_trigger on article;
drop trigger if exists set_last_version_trigger on article;
drop table if exists article;
drop function if exists generate_version_number(regclass, uuid);
drop function if exists set_all_version_to_old(regclass, uuid);
drop trigger if exists generate_version_number_trigger on constitution;
drop trigger if exists set_to_last_version_trigger on constitution;
drop trigger if exists set_last_version_trigger on constitution;
drop table if exists constitution;
drop function if exists set_version_number();
drop function if exists set_to_last_version();
drop function if exists set_last_version();
drop function if exists set_correct_last_version();
-- User
drop table if exists moderator;

View File

@@ -51,7 +51,10 @@ create table moderator
user_id uuid not null references "user" (id)
);
-- Article & Constitution
-------------------------------------
-- Article & Constitution triggers --
-------------------------------------
create or replace function generate_version_number(tablename regclass, version_id uuid, out generated_number int)
language plpgsql as
@@ -83,6 +86,65 @@ begin
end;
$$;
create or replace function set_all_version_to_old(tablename regclass, version_id uuid) returns void
language plpgsql as
$$
declare
_version_id alias for version_id;
begin
if (tablename = 'article'::regclass) then
update article a
set is_last_version = false
where a.version_id = _version_id and a.is_last_version = true;
elseif (tablename = 'constitution'::regclass) then
update constitution c
set is_last_version = false
where c.version_id = _version_id and c.is_last_version = true;
else
raise exception '% is not implemented', tablename::text;
end if;
end;
$$;
create or replace function set_correct_last_version(tablename regclass, version_id uuid) returns void
language plpgsql as
$$
declare
_version_id alias for version_id;
begin
perform set_all_version_to_old(tablename, _version_id);
if (tablename = 'article'::regclass) then
update article a1
set is_last_version = true
from (
select id from article a2
where a2.version_id = _version_id
and a2.is_draft = false
and a2.deleted_at is null
order by version_number desc
limit 1
) as a3
where a1.version_id = _version_id and a1.id = a3.id;
elseif (tablename = 'constitution'::regclass) then
update constitution c1
set is_last_version = true
from (
select id from constitution c2
where c2.version_id = _version_id
and c2.is_draft = false
and c2.deleted_at is null
order by version_number desc
limit 1
) as c3
where c1.version_id = _version_id and c1.id = c3.id;
else
raise exception '% is not implemented', tablename::text;
end if;
end;
$$;
create or replace function set_version_number() returns trigger
language plpgsql as
$$
@@ -92,48 +154,115 @@ begin
end;
$$;
create or replace function set_to_last_version() returns trigger
language plpgsql as
$$
begin
if (new.is_draft = false and new.deleted_at is null) then
perform set_all_version_to_old(tg_table_name::regclass, new.version_id);
new.is_last_version = true;
else
new.is_last_version = false;
end if;
return new;
end;
$$;
create or replace function set_last_version() returns trigger
language plpgsql as
$$
begin
if (new.is_draft != old.is_draft or new.deleted_at != old.deleted_at) then
perform set_correct_last_version(tg_table_name::regclass, new.version_id);
end if;
return new;
end;
$$;
-------------
-- Article --
-------------
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 check ( length(title) < 128 ),
anonymous boolean default false not null,
content text not null check ( content != '' and length(content) < 4096 ),
description text null check ( description != '' and length(description) < 4096 ),
tags varchar(32)[] default '{}' not null,
deleted_at timestamptz default null null,
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 check ( length(title) < 128 ),
anonymous boolean default false not null,
content text not null check ( content != '' and length(content) < 4096 ),
description text null check ( description != '' and length(description) < 4096 ),
tags varchar(32)[] default '{}' not null,
deleted_at timestamptz default null null,
is_draft boolean default false not null,
is_last_version boolean default false not null,
unique (version_id, version_number)
);
create unique index last_version_article_idx on article (is_last_version, version_id) where is_last_version = true;
create trigger generate_version_number_trigger
before insert
on article
for each row
execute function set_version_number();
create trigger set_to_last_version_trigger
before insert
on article
for each row
execute function set_to_last_version();
create trigger set_last_version_trigger
after update
on article
for each row
execute function set_last_version();
------------------
-- Constitution --
------------------
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 check ( length(title) < 128 ),
intro text null check ( length(intro) < 4096 ),
anonymous boolean default false not null,
deleted_at timestamptz default null null,
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 check ( length(title) < 128 ),
intro text null check ( length(intro) < 4096 ),
anonymous boolean default false not null,
deleted_at timestamptz default null null,
is_draft boolean default false not null,
is_last_version boolean default false not null,
unique (version_id, version_number)
);
create unique index last_version_constitution_idx on constitution (is_last_version, version_id) where is_last_version = true;
create trigger generate_version_number_trigger
before insert
on constitution
for each row
execute procedure set_version_number();
create trigger set_to_last_version_trigger
before insert
on constitution
for each row
execute function set_to_last_version();
create trigger set_last_version_trigger
after update
on constitution
for each row
execute function set_last_version();
------
create table title
(
id uuid default uuid_generate_v4() not null primary key,
@@ -364,196 +493,207 @@ create table resource_view
--------------
-- ZOMBO DB --
--------------
-- Filter
SELECT zdb.define_filter('french_stop', '{
"type": "stop",
"stopwords": "_french_",
"ignore_case": true
select zdb.define_filter('french_stop', '{
"type": "stop",
"stopwords": "_french_",
"ignore_case": true
}');
SELECT zdb.define_filter('french_elision', '{
"type": "elision",
"articles": [
"à",
"ainsi",
"alors",
"assez",
"au",
"aussi",
"aux",
"c",
"ça",
"car",
"ce",
"cela",
"ces",
"ceux",
"ci",
"celle",
"celles",
"d",
"de",
"déjà",
"depuis",
"des",
"donc",
"du",
"et",
"ici",
"l",
"la",
"là",
"le",
"les",
"leur",
"leurs",
"ma",
"mais",
"même",
"mes",
"mon",
"ne",
"ni",
"notre",
"nous",
"ou",
"où",
"s",
"sa",
"ses",
"son",
"t",
"ta",
"tant",
"tantôt",
"tels",
"tes",
"ton",
"tôt",
"toujours",
"trop",
"un",
"une",
"votre",
"vos"
],
"ignore_case": true
select zdb.define_filter('french_elision', '{
"type": "elision",
"articles": [
"à",
"ainsi",
"alors",
"assez",
"au",
"aussi",
"aux",
"c",
"ça",
"car",
"ce",
"cela",
"ces",
"ceux",
"ci",
"celle",
"celles",
"d",
"de",
"déjà",
"depuis",
"des",
"donc",
"du",
"et",
"ici",
"l",
"la",
"là",
"le",
"les",
"leur",
"leurs",
"ma",
"mais",
"même",
"mes",
"mon",
"ne",
"ni",
"notre",
"nous",
"ou",
"où",
"s",
"sa",
"ses",
"son",
"t",
"ta",
"tant",
"tantôt",
"tels",
"tes",
"ton",
"tôt",
"toujours",
"trop",
"un",
"une",
"votre",
"vos"
],
"ignore_case": true
}');
SELECT zdb.define_filter('french_stemmer', '{
"type": "stemmer",
"language": "light_french"
select zdb.define_filter('french_stemmer', '{
"type": "stemmer",
"language": "light_french"
}');
SELECT zdb.define_filter('worddelimiter', '{
"type": "word_delimiter"
select zdb.define_filter('worddelimiter', '{
"type": "word_delimiter"
}');
-- Tokenizer
SELECT zdb.define_tokenizer('ngram_tokenizer', '{
select zdb.define_tokenizer('ngram_tokenizer', '{
"type": "nGram",
"min_gram": 3,
"max_gram": 7,
"token_chars": ["letter", "digit"]
"token_chars": [
"letter",
"digit"
]
}');
-- Analyzer
SELECT zdb.define_analyzer('name_analyzer', '{
"type": "custom",
"tokenizer": "ngram_tokenizer",
"filter": ["lowercase", "asciifolding"]
select zdb.define_analyzer('name_analyzer', '{
"type": "custom",
"tokenizer": "ngram_tokenizer",
"filter": [
"lowercase",
"asciifolding"
]
}');
SELECT zdb.define_analyzer('fr_analyzer', '{
"tokenizer": "standard",
"filter": ["french_elision", "worddelimiter", "asciifolding", "lowercase", "french_stop", "french_stemmer"]
select zdb.define_analyzer('fr_analyzer', '{
"tokenizer": "standard",
"filter": [
"french_elision",
"worddelimiter",
"asciifolding",
"lowercase",
"french_stop",
"french_stemmer"
]
}');
-- INDEX article table
SELECT zdb.define_field_mapping('article', 'title', '{
"type": "text",
"analyzer": "fr_analyzer",
"search_analyzer": "fr_analyzer"
select zdb.define_field_mapping('article', 'title', '{
"type": "text",
"analyzer": "fr_analyzer",
"search_analyzer": "fr_analyzer"
}');
SELECT zdb.define_field_mapping('article', 'content', '{
"type": "text",
"analyzer": "fr_analyzer",
"search_analyzer": "fr_analyzer"
select zdb.define_field_mapping('article', 'content', '{
"type": "text",
"analyzer": "fr_analyzer",
"search_analyzer": "fr_analyzer"
}');
SELECT zdb.define_field_mapping('article', 'description', '{
"type": "text",
"analyzer": "fr_analyzer",
"search_analyzer": "fr_analyzer"
select zdb.define_field_mapping('article', 'description', '{
"type": "text",
"analyzer": "fr_analyzer",
"search_analyzer": "fr_analyzer"
}');
CREATE INDEX article_idx
ON article
USING zombodb ((article.*))
WITH (ALIAS='article_idx');
create index article_idx
on article
using zombodb ((article.*))
with (alias ='article_idx');
REINDEX INDEX article_idx;
reindex index article_idx;
-- INDEX constitution table
SELECT zdb.define_field_mapping('constitution', 'title', '{
"type": "text",
"analyzer": "fr_analyzer",
"search_analyzer": "fr_analyzer"
select zdb.define_field_mapping('constitution', 'title', '{
"type": "text",
"analyzer": "fr_analyzer",
"search_analyzer": "fr_analyzer"
}');
SELECT zdb.define_field_mapping('constitution', 'intro', '{
"type": "text",
"analyzer": "fr_analyzer",
"search_analyzer": "fr_analyzer"
select zdb.define_field_mapping('constitution', 'intro', '{
"type": "text",
"analyzer": "fr_analyzer",
"search_analyzer": "fr_analyzer"
}');
CREATE INDEX constitution_idx
ON constitution
USING zombodb ((constitution.*))
WITH (ALIAS='constitution_idx');
create index constitution_idx
on constitution
using zombodb ((constitution.*))
with (alias ='constitution_idx');
REINDEX INDEX constitution_idx;
reindex index constitution_idx;
-- INDEX coment table
SELECT zdb.define_field_mapping('comment', 'content', '{
"type": "text",
"analyzer": "fr_analyzer",
"search_analyzer": "fr_analyzer"
select zdb.define_field_mapping('comment', 'content', '{
"type": "text",
"analyzer": "fr_analyzer",
"search_analyzer": "fr_analyzer"
}');
CREATE INDEX comment_idx
ON comment
USING zombodb ((comment.*))
WITH (ALIAS='comment_idx');
create index comment_idx
on comment
using zombodb ((comment.*))
with (alias ='comment_idx');
REINDEX INDEX comment_idx;
reindex index comment_idx;
-- INDEX citizen table
SELECT zdb.define_field_mapping('citizen', 'first_name', '{
"type": "text",
"analyzer": "name_analyzer",
"search_analyzer": "name_analyzer"
select zdb.define_field_mapping('citizen', 'first_name', '{
"type": "text",
"analyzer": "name_analyzer",
"search_analyzer": "name_analyzer"
}');
SELECT zdb.define_field_mapping('citizen', 'last_name', '{
"type": "text",
"analyzer": "name_analyzer",
"search_analyzer": "name_analyzer"
select zdb.define_field_mapping('citizen', 'last_name', '{
"type": "text",
"analyzer": "name_analyzer",
"search_analyzer": "name_analyzer"
}');
CREATE INDEX citizen_idx
ON citizen
USING zombodb ((citizen.*))
WITH (ALIAS='citizen_idx');
create index citizen_idx
on citizen
using zombodb ((citizen.*))
with (alias ='citizen_idx');
REINDEX INDEX citizen_idx;
reindex index citizen_idx;

View File

@@ -6,6 +6,9 @@ declare
_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", "anonymous": false, "content": "bla bal bla", "tags": ["love", "test"]}';
created_article_v2 json;
first_article_id uuid;
second_article_id uuid;
selected_article json;
selected_total int;
begin
@@ -25,9 +28,14 @@ begin
select upsert_article(created_article) into 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');
assert (created_article->>'is_last_version')::bool = true, 'The first insert must be set to the last version';
first_article_id = (created_article->>'id')::uuid;
-- try to create new version
select upsert_article(created_article) into created_article;
assert (created_article->>'version_number')::int = 2, format('version_number must be equal to 2, %s instead', created_article->>'version_number');
select upsert_article(created_article) into created_article_v2;
assert (created_article_v2->>'version_number')::int = 2, format('version_number must be equal to 2, %s instead', created_article_v2->>'version_number');
assert (created_article_v2->>'is_last_version')::bool = true, 'The second insert must be set to the last version';
second_article_id = (created_article_v2->>'id')::uuid;
-- get articles versions by version_id
select resource, total into selected_article, selected_total from find_articles_versions_by_version_id((created_article->>'version_id')::uuid);
@@ -42,13 +50,29 @@ begin
assert selected_total = 2, format('the total must be 2, %s instead', selected_total);
-- get article by id and check the title
select find_article_by_id((created_article->>'id')::uuid) into selected_article;
select find_article_by_id((created_article_v2->>'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;
select find_last_article_by_version_id((created_article_v2->>'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');
-- update to draft, then the last_version column must be change
update article
set is_draft = true
where id = second_article_id;
select find_last_article_by_version_id((created_article_v2->>'version_id')::uuid) into selected_article;
assert (selected_article->>'version_number')::int = 1, format('version_id must be 1, %s instead', selected_article->>'version_number');
update article
set is_draft = false
where id = second_article_id;
select find_last_article_by_version_id((created_article_v2->>'version_id')::uuid) into selected_article;
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);