From a15847ab9e30746cc3d95537db5ee10e9832548d Mon Sep 17 00:00:00 2001 From: Fabrice Lecomte Date: Sat, 27 Jul 2019 02:45:51 +0200 Subject: [PATCH] feature #4: create function for constitution and title (not article in title) --- .../constitution/find_constitution_by_id.sql | 19 ++++++++ .../find_constitution_titles_by_id.sql | 20 ++++++++ .../constitution/upsert_constitution.sql | 32 +++++++++++++ .../sql/migrations/0000-init_schema.up.sql | 8 ++++ resources/tests/constitution.sql | 46 +++++++++++++++++++ 5 files changed, 125 insertions(+) create mode 100644 resources/functions/constitution/find_constitution_by_id.sql create mode 100644 resources/functions/constitution/find_constitution_titles_by_id.sql create mode 100644 resources/functions/constitution/upsert_constitution.sql create mode 100644 resources/tests/constitution.sql diff --git a/resources/functions/constitution/find_constitution_by_id.sql b/resources/functions/constitution/find_constitution_by_id.sql new file mode 100644 index 0000000..e830051 --- /dev/null +++ b/resources/functions/constitution/find_constitution_by_id.sql @@ -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); \ No newline at end of file diff --git a/resources/functions/constitution/find_constitution_titles_by_id.sql b/resources/functions/constitution/find_constitution_titles_by_id.sql new file mode 100644 index 0000000..8f1e695 --- /dev/null +++ b/resources/functions/constitution/find_constitution_titles_by_id.sql @@ -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); \ No newline at end of file diff --git a/resources/functions/constitution/upsert_constitution.sql b/resources/functions/constitution/upsert_constitution.sql new file mode 100644 index 0000000..0b09868 --- /dev/null +++ b/resources/functions/constitution/upsert_constitution.sql @@ -0,0 +1,32 @@ +create or replace procedure upsert_constitution(inout resource json) + language plpgsql as +$$ +declare + titles json; + new_id uuid; +begin + insert into constitution (version_id, created_by_id, title, annonymous) + select + version_id, + (resource#>>'{created_by, id}')::uuid, + title, + annonymous + from json_populate_record(null::constitution, resource) + returning id into new_id; + + titles := (resource->>'titles'); + + insert into title (created_by_id, name, rank, constitution_id) + select + coalesce((ti#>>'{created_by, id}')::uuid, (resource#>>'{created_by, id}')::uuid), + ti->>'name', + row_number() OVER (), + new_id + from json_array_elements(titles) ti, + lateral json_populate_record(null::title, ti); + + select find_constitution_by_id(new_id) into resource; +end; +$$; + +-- drop procedure if exists upsert_constitution(inout json); \ No newline at end of file diff --git a/resources/sql/migrations/0000-init_schema.up.sql b/resources/sql/migrations/0000-init_schema.up.sql index 0fadcbe..1046234 100644 --- a/resources/sql/migrations/0000-init_schema.up.sql +++ b/resources/sql/migrations/0000-init_schema.up.sql @@ -67,6 +67,13 @@ begin 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; @@ -121,6 +128,7 @@ create table constitution create trigger generate_version_number_trigger before insert on constitution + for each row execute procedure set_version_number(); create table title diff --git a/resources/tests/constitution.sql b/resources/tests/constitution.sql new file mode 100644 index 0000000..2a95203 --- /dev/null +++ b/resources/tests/constitution.sql @@ -0,0 +1,46 @@ +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"]}'; + created_constitution json := '{"version_id":"18ff6dd6-3bc1-4c59-82f0-5e2a8d54ae3e", "title": "Love the world", "annonymous": false, "titles": [{"name":"titleOne"},{"name":"titleTwo"}]}'; +begin + -- insert user for context + call insert_user(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; + 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 title; + delete from constitution; + delete from article; + delete from citizen; + delete from "user"; + + raise notice 'constitution test pass'; +end; +$$; + + +-- select uuid_generate_v4(); \ No newline at end of file