оператор select в функции postgres, вызываемой внутри триггера - PullRequest
1 голос
/ 11 апреля 2019

Я пытаюсь разработать систему уведомлений для серверной части приложения / веб-сайта для социальных сетей.Сейчас я сосредоточен на обновлении статуса.Что я собираюсь сделать, так это поместить в таблицу postgres триггер, связанный с обновлениями статуса, чтобы каждый раз при публикации нового обновления статуса на мой код отправлялось уведомление.

Пока у меня естьбыл в состоянии сделать это.Но дополнительная функция, которую я хотел бы реализовать, - это извлечение всех людей, которые следят за пользователем, опубликовавшим обновление статуса, чтобы я также мог отправить им уведомление о том, что человек, за которым они следят, опубликовал новое обновление статуса.

Конечно, это можно реализовать, сначала получив уведомление о новом обновлении статуса от postgres, извлекая идентификатор пользователя, который его опубликовал, и сделав запрос в базу данных, чтобы выяснить, какие пользователи следуют за ними.

Но я подумал, что будет эффективнее, если я не сделаю запрос, и вместо этого каждый раз, когда postgres хочет отправить мне уведомление о новом обновлении статуса, он также делает запрос, чтобы выяснить, какие пользователиследите за постером обновления статуса и отправьте эту информацию вместе с уведомлением о новом обновлении статуса.

Но я не могу понять, как я могу сделать запрос в функции postgres, которая зависит от аргументаэтой функции, а затем отправить результат этого запроса вместе саргумент в качестве уведомления.

вот что я пробовал:

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();

А затем я слушаю канал событий из своего кода и получаю вставленную строку.Но я хочу сделать оператор select на основе новой строки в моей функции notif () и отправить результат с новой строкой в ​​код прослушивания.

Буду признателен за любые разъяснения

Спасибо

1 Ответ

0 голосов
/ 11 апреля 2019

Как-то так?

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;

Также из комментариев:

Но каким-то волшебным образом return new строка возвращается в уведомлении.

Вы неправильно понимаете вещи. Возврат и уведомление - это две разные вещи.

Прежде всего, давайте разберемся с возвратом.Для триггеров AFTER INSERT возвращаемое значение полностью игнорируется :

Возвращаемое значение триггера уровня строки, запущенного AFTER или триггера уровня оператора, запущенного BEFORE или AFTER, всегда игнорируется;оно также может быть нулевым.

Возвращаемое значение имеет значение только для триггеров BEFORE.В этом случае вы можете изменить (или даже предотвратить) строку перед записью в таблицу.Смотрите это: https://www.postgresql.org/docs/9.2/plpgsql-trigger.html Это не имеет ничего общего с уведомлениями.

Так что насчет уведомлений? Все, что вы получаете из уведомления, это то, что вы передаете в качестве второго аргумента pg_notify. Все это довольно хорошо задокументировано: https://www.postgresql.org/docs/9.0/sql-notify.html

...