select statement in postgres function called inside a trigger

╄→гoц情女王★ 提交于 2021-01-28 08:15:15

问题


I'm trying to develop a notification system for the backend of a social media application/website. For now I'm focusing on status updates. What I'm going to do, is putting a trigger on the postgres table that related to status updates so that every time a new status update is posted, a notification is sent to my code.

So far I have been able to do that. But an extra feature that I like to implement is extracting all of the people who follow the user who posted the status update, so that I can also send them a notification that the person they're following has posted a new status update.

Of course it can be implemented by first receiving the notification for a new status update from postgres, extracting the user id of the person who posted it, and make a query to the database to find out which users follow them.

But I figured it would be more efficient if I don't make the query, and instead, each time postgres wants to send me a notification about a new status update, it also makes a query to find out which users are following the poster of the status update and send that information along with the notification for the new status update.

But I can't figure out how I can make a query in a postgres function that depends on the argument of that function, and then send the result of that query along with the argument as a notification.

this is what I've tried:

create table example (c1 text, c2 text);

create function notif() 
   returns trigger as 
$$ 
begin 
  perform pg_notify('event',row_to_json(new)::text); 
  return new; 
end; 
$$ language plpgsql;

create trigger trig after insert 
   on example 
   for each row execute procedure notif();

And then I listen to the event channel from my code and receive the row that was inserted. But I want to do a select statement based on the new row in my notif() function and send the result with the new row to the listening code.

I'd appreciate any clarification

Thanks


回答1:


Something like this?

CREATE FUNCTION notif()
RETURNS TRIGGER AS $$
DECLARE
    data JSONB;
    result JSONB;
BEGIN
    SELECT json_agg(tmp)  -- requires Postgres9.3+
    INTO data
    FROM (
        -- your subquery goes here, for example:
        SELECT followers.following_user_id
        FROM followers
        WHERE followers.followed_user_id = NEW.user_id
    ) tmp;

    result := json_build_object('data', data, 'row', row_to_json(NEW));
    PERFORM pg_notify('event', result::TEXT);
    RETURN NEW;
END;
$$ language plpgsql;

Also from comments:

But somehow magically using return new the row is returned within the notification.

You misunderstand things. Return and notification are two different things.

First of all lets deal with return. For AFTER INSERT triggers the return value is totally ignored:

The return value of a row-level trigger fired AFTER or a statement-level trigger fired BEFORE or AFTER is always ignored; it might as well be null.

The return value only matters for BEFORE triggers. In which case you can modify (or even prevent) the row before writing to the table. See this: https://www.postgresql.org/docs/9.2/plpgsql-trigger.html This has nothing to do with notifications.

So what about notifications? Whatever you receive from a notification is what you pass as second argument to pg_notify. All of that is quite well documented: https://www.postgresql.org/docs/9.0/sql-notify.html



来源:https://stackoverflow.com/questions/55624633/select-statement-in-postgres-function-called-inside-a-trigger

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!