Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
set check_function_bodies = off;

CREATE OR REPLACE FUNCTION public.fetch_gem_with_people(gem_id_param uuid)
RETURNS jsonb
LANGUAGE plpgsql
AS $function$
DECLARE
gem_data_var jsonb;
lines_data_var jsonb;
people_data_var jsonb;
BEGIN
SELECT
row_to_json(g) INTO gem_data_var
FROM
public.gems g
WHERE
g.id = gem_id_param
LIMIT 1;
-- The client model requires the `gem_share_tokens` key to be present, even
-- though it's not needed here.
gem_data_var := jsonb_set(gem_data_var, '{gem_share_tokens}', 'null'::jsonb, TRUE);
-- Fetch the lines associated with the gem
SELECT
jsonb_agg(DISTINCT l) FILTER (WHERE l.id IS NOT NULL) INTO lines_data_var
FROM
public.lines l
WHERE
l.gem_id = gem_id_param;
-- Fetch the people associated with the lines
SELECT
jsonb_agg(DISTINCT p) FILTER (WHERE p.id IS NOT NULL) INTO people_data_var
FROM
public.people p
WHERE
p.id IN (
SELECT
l.person_id
FROM
public.lines l
WHERE
l.gem_id = gem_id_param);
-- Combine gem_data, lines_data, and people_data into a single JSONB object
RETURN jsonb_build_object('gem', jsonb_set(gem_data_var, '{lines}', coalesce(lines_data_var, '[]'::jsonb), TRUE), 'people', people_data_var);
END;
$function$
;
5 changes: 4 additions & 1 deletion supabase/schemas/public/functions/fetch_gem_with_people.sql
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ BEGIN
WHERE
g.id = gem_id_param
LIMIT 1;
-- The client model requires the `gem_share_tokens` key to be present, even
-- though it's not needed here.
gem_data_var := jsonb_set(gem_data_var, '{gem_share_tokens}', 'null'::jsonb, TRUE);
-- Fetch the lines associated with the gem
SELECT
jsonb_agg(DISTINCT l) FILTER (WHERE l.id IS NOT NULL) INTO lines_data_var
Expand All @@ -35,6 +38,6 @@ BEGIN
WHERE
l.gem_id = gem_id_param);
-- Combine gem_data, lines_data, and people_data into a single JSONB object
RETURN jsonb_build_object('gem', jsonb_set(gem_data_var, '{lines}', lines_data_var, TRUE), 'people', people_data_var);
RETURN jsonb_build_object('gem', jsonb_set(gem_data_var, '{lines}', coalesce(lines_data_var, '[]'::jsonb), TRUE), 'people', people_data_var);
END;
$function$;
98 changes: 98 additions & 0 deletions supabase/tests/public/functions/fetch_gem_with_people.test.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
BEGIN;
SELECT no_plan();

-- Arrange (shared setup)
SELECT tests.create_chucklechest_user('owner');
SELECT tests.create_chest('owner') AS chest_id \gset

SELECT tests.authenticate_as_service_role();
INSERT INTO public.people (nickname, date_of_birth, chest_id)
VALUES ('Alice', '1990-01-01', :'chest_id')
RETURNING id AS person_id \gset

SAVEPOINT arrange_all;


-- Arrange
SELECT tests.authenticate_as_service_role();
INSERT INTO public.gems (number, occurred_at, chest_id)
VALUES (1, '2024-06-15'::date, :'chest_id')
RETURNING id AS gem_id \gset

INSERT INTO public.lines (text, gem_id, chest_id, person_id)
VALUES ('Hello!', :'gem_id', :'chest_id', :person_id);

-- Act
SELECT public.fetch_gem_with_people(:'gem_id') AS result \gset

-- Assert
SELECT is(
(:'result'::jsonb -> 'gem' -> 'gem_share_tokens'),
'null'::jsonb,
'Given: gem with no share token. When: fetch_gem_with_people called. Then: gem_share_tokens key is present with a JSON null value (client model requires the key to exist).'
);

SELECT is(
jsonb_array_length(:'result'::jsonb -> 'gem' -> 'lines'),
1,
'Given: gem with one line. When: fetch_gem_with_people called. Then: lines array has 1 entry.'
);

SELECT is(
(:'result'::jsonb -> 'gem' -> 'lines' -> 0 ->> 'text'),
'Hello!',
'Given: gem with one line. When: fetch_gem_with_people called. Then: lines array contains the line text.'
);

SELECT is(
(:'result'::jsonb -> 'people' -> 0 ->> 'nickname'),
'Alice',
'Given: line assigned to a person. When: fetch_gem_with_people called. Then: people array contains that person.'
);


ROLLBACK TO arrange_all;


-- Arrange
SELECT tests.authenticate_as_service_role();
INSERT INTO public.gems (number, occurred_at, chest_id)
VALUES (1, '2024-06-15'::date, :'chest_id')
RETURNING id AS gem_id \gset

INSERT INTO public.lines (text, gem_id, chest_id, person_id)
VALUES ('Just narration.', :'gem_id', :'chest_id', NULL);

-- Act
SELECT public.fetch_gem_with_people(:'gem_id') AS result \gset

-- Assert
SELECT is(
(:'result'::jsonb -> 'people'),
'null'::jsonb,
'Given: gem with no lines assigned to a person. When: fetch_gem_with_people called. Then: people is null.'
);


ROLLBACK TO arrange_all;


-- Arrange
SELECT tests.authenticate_as_service_role();
INSERT INTO public.gems (number, occurred_at, chest_id)
VALUES (1, '2024-06-15'::date, :'chest_id')
RETURNING id AS gem_id \gset

-- Act
SELECT public.fetch_gem_with_people(:'gem_id') AS result \gset

-- Assert
SELECT is(
(:'result'::jsonb -> 'gem' ->> 'id')::uuid,
:'gem_id'::uuid,
'Given: gem with zero lines. When: fetch_gem_with_people called. Then: gem data is still returned (not nulled out).'
);


SELECT * FROM finish();
ROLLBACK;
Loading