LISTEN/NOTIFY, используя pg_notify (текст, текст) в PostgreSQL

Я играл с системой уведомлений PostgreSQL и не могу на всю жизнь выяснить, почему pg_notify (текст, текст) никогда не работает. Эта функция не слишком задокументирована, и я не могу найти много примеров ее использования в дикой природе, поэтому я решил, что никто не возражает, что я спрашиваю здесь.

Выполнение следующих работ точно так, как ожидалось:

LISTEN my_channel;

NOTIFY my_channel, 'my message text';

Использование функции pg_notify(), однако, возвращает нулевое значение, и никакое уведомление не отправляется. Ошибка не указана. Пример использования:

SELECT pg_notify('my_channel', 'my message text');

Я мог бы использовать функцию NOTIFY, но моя цель - упорядочить уведомление в запросе следующим образом:

select pg_notify(get_player_error_channel(username)::TEXT, 'test'::TEXT)
    from player;

Я предполагаю, что я должен упустить что-то смешное, но мне не повезло, объясняя причину этого. Страница обсуждения NOTIFY можно найти здесь: http://www.postgresql.org/docs/9.0/static/sql-notify.html

В нем упоминается об этом pg_notify(), что заставляет меня предположить, что ничего принципиально не изменится.

pg_notifyЧтобы отправить уведомление, вы также можете использовать функцию pg_notify (текст, текст). Функция принимает имя канала в качестве первого аргумента и полезную нагрузку как вторую. Функция намного проще в использовании, чем команда NOTIFY, если вам нужно работать с непостоянными названиями каналов и полезными нагрузками.

Спасибо, как всегда за помощь

Изменить: версия базы данных: "PostgreSQL 9.0.3 на i686-pc-linux-gnu, скомпилированный GCC gcc (GCC) 4.2.4, 32-разрядный"

Ответы

Ответ 1

Я обсуждал это в списке рассылки PostgreSQL (http://archives.postgresql.org/pgsql-bugs/2011-03/msg00041.php) и был проинформирован о причинах поведения.

Их ответ заключается в том, что ".. вам нужно удвоить цитату с отступлением (слушать" тест "). хотите, чтобы сервер не сбрасывал их. pg_notify принимает строку, а не relname, в котором используются разные правила ". (Спасибо Merlin и Tom)

Это означает, что следующее работает, потому что канал всегда вынужден использовать нижний регистр

LISTEN ERRORCHANNEL;

NOTIFY ERRORCHANNEL, 'something!';
NOTIFY eRrorChanNel, 'something!';

Если вам нужно добавить двойные кавычки вокруг имени канала, это будет поддерживаться.

Итак, со следующим, вы получите первое уведомление, но не второе:

LISTEN "ERRORCHANNEL";

NOTIFY "ERRORCHANNEL", 'something!'; 
NOTIFY "eRrorChanNel", 'something!';

Аналогично, следующее будет работать, потому что двойные кавычки заставляют поддерживать ERRORCHANNEL:

LISTEN "ERRORCHANNEL";

SELECT pg_notify('ERRORCHANNEL', 'something!');

Пока это не сработает:

LISTEN ERRORCHANNEL;

SELECT pg_notify('ERRORCHANNEL', 'something!');

В этой ситуации ERRORCHANNEL не находится в двойных кавычках в команде LISTEN, поэтому PostgreSQL заставляет ее ограничивать регистр. Параметр канала имеет тип текста, а не relname, поэтому случай не затрагивается функцией pg_notify(). Вместе каналы не совпадают (ERRORCHANNE!= Errorchannel), поэтому уведомление никогда не принимается.

Ответ 2

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

Отсутствует "push" от сервера к клиенту.

В JDBC вам нужно запустить какой-то оператор SELECT, а затем все ожидающие уведомления будут доступны в объекте Connection (см. http://jdbc.postgresql.org/documentation/head/listennotify.html)

Я не знаю, как это работает для других языков программирования. Я думаю, что libpq (C/С++) имеет специальные функции для прямого извлечения уведомлений без запуска select