Использование pg_notify в триггерной функции PostgreSQL

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

Эта версия моей функции триггера работает должным образом. У меня есть программа на Java, которая СЛУШАЕТ "mymessage" и получает уведомление с полезной нагрузкой "запущено NOTIFY".

-- Function: conversation_notify()

-- DROP FUNCTION conversation_notify();

CREATE OR REPLACE FUNCTION conversation_notify()
  RETURNS trigger AS
$BODY$
    BEGIN
        --SELECT pg_notify('mymessage', 'fired by FUNCTION');
        NOTIFY mymessage, 'fired by NOTIFY';
        RETURN NULL;
    END; 
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION conversation_notify() OWNER TO postgres;

Эта версия моей функции триггера НЕ работает должным образом. Единственные изменения - раскомментирование строки pg_notify и комментирование строки NOTIFY ниже. (Я не изменял Java-приложение, которое ПРОСЛУШАЕТ.) Я ожидаю, что мое приложение, ПРОСЛУШАЮЩЕЕ «mymessage», получит уведомление с полезной нагрузкой «запущено FUNCTION». Фактическое поведение таково, что ничего не получено, даже через 30+ секунд после изменения соответствующей таблицы.

-- Function: conversation_notify()

-- DROP FUNCTION conversation_notify();

CREATE OR REPLACE FUNCTION conversation_notify()
  RETURNS trigger AS
$BODY$
    BEGIN
        SELECT pg_notify('mymessage', 'fired by FUNCTION');
        --NOTIFY mymessage, 'fired by NOTIFY';
        RETURN NULL;
    END; 
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION conversation_notify() OWNER TO postgres;

Однако я действительно запутался, потому что та же самая команда pg_notify работает, как и ожидалось, из консоли psql! Когда я выполняю следующую команду, мое приложение Java получает уведомление с полезной нагрузкой «запущено CONSOLE»:

select pg_notify('mymessage', 'fired by CONSOLE');

Для полноты, вот мое определение триггера:

-- Trigger: conversation_notify on ofconversation

-- DROP TRIGGER conversation_notify ON ofconversation;

CREATE TRIGGER conversation_notify
  AFTER INSERT OR UPDATE
  ON ofconversation
  FOR EACH ROW
  EXECUTE PROCEDURE conversation_notify();

Я пытаюсь использовать pg_notify, потому что я хотел бы иметь динамическую полезную нагрузку. Прямо сейчас это спорный вопрос. :) В руководстве Postgres 9.0 указано, что это должно быть возможно. Документы NOTIFY для состояния параметра «полезная нагрузка»:

(Если необходимо передать двоичные данные или большие объемы информации, лучше всего поместить их в таблицу базы данных и отправить ключ записи .)

Я также сослался на связанный вопрос о переполнении стека, и, думаю, я избежал этой проблемы: СЛУШАТЬ / УВЕДОМЛЕНИЕ с помощью pg_notify (текст, текст) в PostgreSQL .

База данных версия:

PostgreSQL 9.0.3, скомпилирована Visual C ++ build 1500, 32-разрядная версия

Моя ОС - Windows XP Professional, версия 2002, SP3.

Заранее спасибо.

РЕДАКТИРОВАТЬ: ниже добавлен код прослушивателя Java. Он основан на этом примере из документации PostgreSQL: http://jdbc.postgresql.org/documentation/81/listennotify.html .

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import org.postgresql.PGConnection;
import org.postgresql.PGNotification;

public class ConversationListener extends Thread
{   
    private Connection conn;
    private PGConnection pgConn;

    public ConversationListener(Connection conn) throws SQLException
    {
        this.conn = conn;
        this.pgConn = (PGConnection) conn;
        Statement listenStatement = conn.createStatement();
        listenStatement.execute("LISTEN mymessage");
        listenStatement.close();
    }

    @Override
    public void run()
    {
        while (true)
        {
            try
            {
                // issue a dummy query to contact the backend
                // and receive any pending notifications.
                Statement selectStatement = conn.createStatement();
                ResultSet rs = selectStatement.executeQuery("SELECT 1");
                rs.close();
                selectStatement.close();

                PGNotification notifications[] = pgConn.getNotifications();

                if (notifications != null)
                {
                    for (PGNotification pgNotification : notifications)
                    {
                        System.out.println("Got notification: " + pgNotification.getName() +
                            " with payload: " + pgNotification.getParameter());
                    }
                }

                // wait a while before checking again
                Thread.sleep(500);
            }
            catch (SQLException sqlException)
            {
                sqlException.printStackTrace();
            }
            catch (InterruptedException ie)
            {
                ie.printStackTrace();
            }
        }
    }
}

Это простое настольное приложение Java 1.6 SE, поэтому я ' Я управляю своим собственным JDBC-соединением и всем остальным. Я загружаю драйвер через

Class.forName("org.postgresql.Driver");

. Я использую библиотеку postgresql-9.0-801.jdbc3.jar (только одну в моем пути к классам) и JDK 1.6.0_22.

Напомню, что Java код отлично работает с NOTIFY из psql и триггером, а также с pg_notify из psql.

18
задан Community 23 May 2017 в 10:31
поделиться