Russian Qt Forum

Qt => Базы данных => Тема начата: Pupil от Июнь 18, 2013, 14:50



Название: События с Postgres
Отправлено: Pupil от Июнь 18, 2013, 14:50
Здравствуйте!

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

Погуглил, нашел тему на данном форуме.

К таблице дописываю правило:

Код:
CREATE OR REPLACE RULE notify_report_rule AS
    ON UPDATE TO report DO
 NOTIFY report_update;

В заголовочном файле пишу:

Код:
void slotGetNotify(const QString& notification); //Изменена таблица report в БД

в конструкторе окна:

Код:
QSqlDatabase::database().driver()->subscribeToNotification("report_update");

connect(QSqlDatabase::database().driver(), SIGNAL(notification(const QString&)), this,
                SLOT( slotGetNotify(const QString&) ) );
//Изменена таблица report в БД

Код:
qDebug()
выдает следующее:

QPSQLDriver::subscribeToNotificationImplementation: already subscribing to 'report_update'.

Если я правильно мыслю, то в данном случае необходимо создавать второе подключение к базе?

Попробовал другой путь:

на уровне базы данных создал триггер и функцию
Код:
CREATE OR REPLACE FUNCTION report_stamp()
  RETURNS trigger AS
$BODY$
    BEGIN
        -- Check update reportn_report and reportr_report in report table
        IF UPDATE.reportn_report
        THEN
            NOTIFY virtual;
        END IF;
        IF UPDATE.reportr_report
        THEN
            NOTIFY virtual;
        END IF;
             
    END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION report_stamp()
  OWNER TO postgres;

В таком случае в QSqlTableModel данные просто не отображаются.
И, если возможно, реализовать триггер и функцию на уровне СУБД, то как это перехватывать в классе?  Также с помощью:

Код:
connect(QSqlDatabase::database().driver(), SIGNAL(notification(const QString&)), this,
                SLOT( slotGetNotify(const QString&) ) );
?


Qt 4.8, Postgre 9.0.1


Название: Re: События с Postgres
Отправлено: Pupil от Июнь 19, 2013, 08:54
Код:
CREATE OR REPLACE FUNCTION report_stamp()
  RETURNS trigger AS
$BODY$
    BEGIN
        -- Check update reportn_report and reportr_report in report table
        IF UPDATE reportn_report
        THEN
            NOTIFY virtual;
        END IF;
        IF UPDATE reportr_report
        THEN
            NOTIFY virtual;
        END IF;
             
    END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  ALTER FUNCTION report_stamp()
  OWNER TO postgres;

Подправил условие. При этом проявился следующий интересный момент - QSqlTableModel таблицу отобразила, а запросы на изменение данных из класса не проходят )


Название: Re: События с Postgres
Отправлено: Pupil от Июнь 19, 2013, 10:30
Разобрался с принципом конструирования триггера и функции. Если удастся решить задачу - скину и алгоритм и линки полезные.
Но эффект такой же остался - таблица отображается в модели, а при попытке запроса на изменение или добавление данных - QSqlTableModel не обновляется!
При удалении триггера с функцией - всё функционирует корректно.

Код:

CREATE OR REPLACE FUNCTION send_log()
  RETURNS trigger AS
$BODY$
DECLARE
    mstr varchar(30);
    astr varchar(100);
    retstr varchar(254);
BEGIN
    IF  TG_OP = 'INSERT' THEN
        astr = NEW.name;
        mstr := 'Add new report ';
        retstr := mstr || astr;
        NOTIFY virtual;
        --INSERT INTO logs(text,added) values (retstr,NOW());
        RETURN NEW;
    ELSIF TG_OP = 'UPDATE' THEN
        astr = NEW.name;
        mstr := 'Update report ';
        retstr := mstr || astr;
        NOTIFY virtual;
        --INSERT INTO logs(text,added) values (retstr,NOW());
        RETURN NEW;
    ELSIF TG_OP = 'DELETE' THEN
        astr = OLD.name;
        mstr := 'Remove report ';
        retstr := mstr || astr;
        NOTIFY virtual;
        --INSERT INTO logs(text,added) values (retstr,NOW());
        RETURN OLD;
    END IF;
END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION send_log()
  OWNER TO postgres;


CREATE TRIGGER t_report
  AFTER INSERT OR UPDATE OR DELETE
  ON report
  FOR EACH ROW
  EXECUTE PROCEDURE send_log();


Название: Re: События с Postgres
Отправлено: Pupil от Июнь 19, 2013, 13:04
База NOTIFY отдает. Осталось отловить PID с переменным значением )


Название: Re: События с Postgres
Отправлено: Pupil от Июнь 19, 2013, 16:02
Иссяк! Хэлп ми, плиз. ))) Крокодил не ловится, не ловится кокос. Не могу отловить сигнал от базы.
Надо ли как-то по-особенному настраивать базу, чтобы QSqlDriver ловил события?

Спасибо всем!


Название: Re: События с Postgres
Отправлено: Pupil от Июнь 20, 2013, 12:44
Прикладываю пример со скриптами в файле main

Выяснил что (благодарю за совет промоделировать на отдельном простом примере!):

В общем проекте notify не получает приложение ещё и из-за кодировки. Прописал принудительно кодек UTF-8 - нормальное мышление отказывается понять такой выкрутас создателей )

Что касается примера, приложенного к посту, то в нем при изменении таблицы из самого проекта notify не появляется никак, а вот при ковырянии значений в PGAdmine ручками или с помощью скриптов в консоли вывело notify в приложение.

Изучив собственный опыт 36 ступеней Шаолиня и документацию (перевод с Анлицкого) предположу следующее:

а) notify не дадено получать приложению, совершившему изменение базы и ловящему сигнал об этом изменении
б) Это недостаток драйвера для Qt 4.8
в) Возможно, есть другой способ как "поймать" notify в приложении, но мне он неизвестен. )

Обновление на Qt 5.0.2 не предлагать - не свободный фрилансер я. )


Название: Re: События с Postgres
Отправлено: lit-uriy от Июнь 20, 2013, 19:41
>notify не дадено получать приложению, совершившему изменение базы и ловящему сигнал об этом изменении
а что по этому поводу пишут в документации на СУБД?


Название: Re: События с Postgres
Отправлено: Pupil от Июнь 21, 2013, 07:36
Если я правильно мыслю, то СУБД шлёт широковещательный сигнал наверх, а вот драйвер Qt  PSQL необходимо дотачивать как написано в одной из тем данного сайта. )


Название: Re: События с Postgres
Отправлено: lit-uriy от Июнь 22, 2013, 14:07
про PostgreSQL не знаю, Firebird шлёь только тем, кто подписался на уведомление


Название: Re: События с Postgres
Отправлено: Pupil от Июнь 23, 2013, 10:43
Postgre шлёт всем, кроме того, который сделал изменение в базе. ) Но теория и практика как показывает жизнь - понятия редко идеально совместимые. )


Название: Re: События с Postgres
Отправлено: Hellraiser от Июль 08, 2013, 12:41
Появилась необходимость обработки уведомлений и у меня. PostgreSQL 9.2, Qt 4.8.5, драйвер из стандартной сборки Qt. В такой связке уведомления от базы приходят всем, включая сделавшего изменения.