Russian Qt Forum
Ноябрь 23, 2024, 05:46 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: События с Postgres  (Прочитано 11634 раз)
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
Записан
Pupil
Гость
« Ответ #1 : Июнь 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 таблицу отобразила, а запросы на изменение данных из класса не проходят )
Записан
Pupil
Гость
« Ответ #2 : Июнь 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();
Записан
Pupil
Гость
« Ответ #3 : Июнь 19, 2013, 13:04 »

База NOTIFY отдает. Осталось отловить PID с переменным значением )
Записан
Pupil
Гость
« Ответ #4 : Июнь 19, 2013, 16:02 »

Иссяк! Хэлп ми, плиз. ))) Крокодил не ловится, не ловится кокос. Не могу отловить сигнал от базы.
Надо ли как-то по-особенному настраивать базу, чтобы QSqlDriver ловил события?

Спасибо всем!
Записан
Pupil
Гость
« Ответ #5 : Июнь 20, 2013, 12:44 »

Прикладываю пример со скриптами в файле main

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

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

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

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

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

Обновление на Qt 5.0.2 не предлагать - не свободный фрилансер я. )
Записан
lit-uriy
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3880


Просмотр профиля WWW
« Ответ #6 : Июнь 20, 2013, 19:41 »

>notify не дадено получать приложению, совершившему изменение базы и ловящему сигнал об этом изменении
а что по этому поводу пишут в документации на СУБД?
Записан

Юра.
Pupil
Гость
« Ответ #7 : Июнь 21, 2013, 07:36 »

Если я правильно мыслю, то СУБД шлёт широковещательный сигнал наверх, а вот драйвер Qt  PSQL необходимо дотачивать как написано в одной из тем данного сайта. )
Записан
lit-uriy
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3880


Просмотр профиля WWW
« Ответ #8 : Июнь 22, 2013, 14:07 »

про PostgreSQL не знаю, Firebird шлёь только тем, кто подписался на уведомление
Записан

Юра.
Pupil
Гость
« Ответ #9 : Июнь 23, 2013, 10:43 »

Postgre шлёт всем, кроме того, который сделал изменение в базе. ) Но теория и практика как показывает жизнь - понятия редко идеально совместимые. )
Записан
Hellraiser
Бывалый
*****
Offline Offline

Сообщений: 451


Просмотр профиля
« Ответ #10 : Июль 08, 2013, 12:41 »

Появилась необходимость обработки уведомлений и у меня. PostgreSQL 9.2, Qt 4.8.5, драйвер из стандартной сборки Qt. В такой связке уведомления от базы приходят всем, включая сделавшего изменения.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.051 секунд. Запросов: 23.