I need help to complete the following requirements:
Profile
table with columns id
, username
, ...Comment
table with columns id
, content
, ...CommentReference
table with columns id
, profile_id
, comment_id
, ...When a new comment is created, before inserting:
NEW.content
have references to usernames, like @someusername
CommentReferences
the profile and commentFor now, what I have is the following code:
PS: the following code has errors, I need help to fix it. I'm using postgres version 12.
CREATE FUNCTION create_comment_usernames_references()
RETURNS trigger AS $$
DECLARE usernames TEXT[];
DECLARE username TEXT;
DECLARE profile_id TEXT; -- profile_id is of type uuid, is it correct to use TEXT here?
BEGIN
-- verify if there are usernames in the comment.content with the username regex
SELECT DISTINCT(
regexp_matches(
NEW.content,
'@(([a-z0-9]*((?<=[a-z0-9])[-|_|\.](?=[a-z0-9]))[a-z0-9]*)*|[a-z0-9]*)',
'g'
)
)[1]
INTO usernames;
FOREACH username IN ARRAY usernames LOOP
SELECT (SELECT id FROM "public"."Profile" WHERE "username" = username) INTO profile_id
INSERT INTO "public"."CommentReference" (comment_id, profile_id) VALUES (NEW.id, profile_id);
END LOOP;
-- return nothing
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER create_comment_usernames_references_trigger
BEFORE INSERT OR UPDATE ON "public"."Comment"
FOR EACH ROW
EXECUTE PROCEDURE create_comment_usernames_references();
Solve it myself.
Final code:
CREATE OR REPLACE FUNCTION find_profile_ids_by_usernames_in_text(_value TEXT)
RETURNS TABLE (profile_id uuid) AS
$func$
BEGIN
RETURN QUERY
SELECT
id
FROM
"public"."Profile"
WHERE
username IN (
SELECT DISTINCT(
regexp_matches(
_value,
'@(([a-z0-9]*((?<=[a-z0-9])[-|_|\.](?=[a-z0-9]))[a-z0-9]*)*|[a-z0-9]*)',
'g')
)[1]
);
END
$func$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION create_comment_reference(_comment_id UUID, _content TEXT)
RETURNS integer AS $$
DECLARE
row RECORD;
BEGIN
FOR row IN
SELECT * FROM find_profile_ids_by_usernames_in_text(_content)
LOOP
INSERT INTO
"public"."CommentReference" (comment_id, profile_id)
VALUES
(_comment_id, row.profile_id)
ON CONFLICT DO NOTHING;
END LOOP;
RETURN 1;
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION create_comment_reference_trigger_func()
RETURNS trigger AS $$
DECLARE someval integer;
BEGIN
select * from create_comment_reference(NEW.id, NEW.content) into someval;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER create_comment_usernames_references_trigger
AFTER INSERT OR UPDATE ON "public"."Comment"
FOR EACH ROW
EXECUTE PROCEDURE create_comment_reference_trigger_func();