Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / как при появлении новой записи в БД оповестить об этом внешнюю программу? / 22 сообщений из 22, страница 1 из 1
05.08.2014, 14:02:30
    #38713048
Marina.M
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как при появлении новой записи в БД оповестить об этом внешнюю программу?
Есть такая задача - БД на Postgresql и Qt-программа. Необходимо, чтобы при появлении новой записи в таблице БД оповещение об этом приходило на Qt-программу, которая считает эту запись. Каким образом это можно реализовать?
...
Рейтинг: 0 / 0
05.08.2014, 14:16:19
    #38713068
Триггерман
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как при появлении новой записи в БД оповестить об этом внешнюю программу?
Marina.M,

А может наоборот - программа будет периодически по таймеру просматривать таблицу на предмет наличия присутствия новой записи ?
...
Рейтинг: 0 / 0
05.08.2014, 14:19:59
    #38713072
V&N
V&N
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как при появлении новой записи в БД оповестить об этом внешнюю программу?
Marina.M,
NOTIFY , LISTEN , UNLISTEN
...
Рейтинг: 0 / 0
05.08.2014, 14:29:16
    #38713081
rovan
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как при появлении новой записи в БД оповестить об этом внешнюю программу?
V&NMarina.M,
NOTIFY , LISTEN , UNLISTEN
Ога. Однако, там были проблемы с уведомлением самого себя о внесенных самим собой изменениях.
То есть:
1. Программа А сделала апдейт строки
2. Сервер проапдейтил строку.
3. Сервер отправил нотификацию.
4. Программа А не получила нотификацию.

ТС, проверь этот момент хорошо, может быть, уже исправили.
...
Рейтинг: 0 / 0
05.08.2014, 16:10:39
    #38713246
Marina.M
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как при появлении новой записи в БД оповестить об этом внешнюю программу?
ТриггерманMarina.M,

А может наоборот - программа будет периодически по таймеру просматривать таблицу на предмет наличия присутствия новой записи ?

это легко, но не подходит
...
Рейтинг: 0 / 0
05.08.2014, 16:29:47
    #38713281
Marina.M
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как при появлении новой записи в БД оповестить об этом внешнюю программу?
V&NMarina.M,
NOTIFY , LISTEN , UNLISTEN

Спасибо. Посмотрю
...
Рейтинг: 0 / 0
05.08.2014, 18:44:04
    #38713404
Sergei.Agalakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как при появлении новой записи в БД оповестить об этом внешнюю программу?
Классическое решение - использование очереди сообщений. При изменении данных в таблице сообщение об этом помещается в очередь сообщений, и в дальнейшем асинхронно читается клиентом.
В простых случаях хватает NOTIFY, LISTEN, UNLISTEN, как уже говорили. Можно поглядеть на PgQ из Skytools или, если вся архитектура информационной системы завязана на очереди сообщений, выбрать срециалтзтрованные решения.
...
Рейтинг: 0 / 0
06.08.2014, 13:41:26
    #38714091
Marina.M
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как при появлении новой записи в БД оповестить об этом внешнюю программу?
Sergei.AgalakovКлассическое решение - использование очереди сообщений. При изменении данных в таблице сообщение об этом помещается в очередь сообщений, и в дальнейшем асинхронно читается клиентом.
В простых случаях хватает NOTIFY, LISTEN, UNLISTEN, как уже говорили. Можно поглядеть на PgQ из Skytools или, если вся архитектура информационной системы завязана на очереди сообщений, выбрать срециалтзтрованные решения.

спасибо. идеально для решения подошел пример из вот этой ссылки http://www.prog.org.ru/index.php?topic=25053.msg178942
...
Рейтинг: 0 / 0
29.08.2014, 10:10:29
    #38732394
Marina.M
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как при появлении новой записи в БД оповестить об этом внешнюю программу?
Возник еще один вопрос по поводу получения оповещений из базы данных в проекте на Qt.

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

Ссылка на этот форум: http://www.forum.crossplatform.ru/index.php?showtopic=9176

Действительно ли только таким образом можно решить эту проблему или есть более простые решения получить номер записи, где произошло изменение?
...
Рейтинг: 0 / 0
29.08.2014, 10:37:04
    #38732412
buddy_ekb
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как при появлении новой записи в БД оповестить об этом внешнюю программу?
Marina.M,

если версия postgresql >= 9.0, то notify/listen умеют передавать и принимать дополнительное текстовое поле (payload).
...
Рейтинг: 0 / 0
31.08.2014, 22:38:38
    #38733714
Mavr747
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как при появлении новой записи в БД оповестить об этом внешнюю программу?
Marina.M, Конкретно на xBase++ (просто пишу на нем)
----------------
// Get server notify if exist (этот участок крутится в петле)
If PQconsumeInput(oConn:pDB) = 1 // функция из libpg.dll
If ((notify := PQnotifies(oConn:pDB)) != 0) // функция из libpg.dll
oInfo := pgNotify():new()
oInfo:_link_(notify,.F.)
ExecuteNotify( oDialog:oCurBrowser, oInfo ) // Смотрим далее...
PQfreeNotify(notify)
nNotifies++
oInfo := NIL
EndIf
EndIf
-----------------
FUNCTION ExecuteNotify( browser, oNotify )
local cLine, cTable, i, aFindRec, nOldRec, nRec, nHwnd
local cMessage := oNotify:cExtra
local cChannel := oNotify:cRelName
local nPid := oNotify:be_pid // а это process id
..... далее в коде ..... ExecuteNotify .....
// Is other station send notify?
If nPid <> browser:table:oPG:backendPID
а при создании oPG...[ ::backendPID := PQbackendPID( ::pDB )] // функция из libpg.dll

Посылка из другого клиентского приложения всем кто слушает
::table:oPG:SendNotify(::table:cTable+":APPEND RECORD") // посылаю имя таблицы и текст что случилось

METHOD XBPgSql:SendNotify( cNotify ) // Реализация метода посылки
local res
If !Empty(::notifyChannel)
res := PQexec( ::pDB, "NOTIFY " + ::notifyChannel + ", '"+cNotify+"'" ) // функция из libpg.dll


как то так...
...
Рейтинг: 0 / 0
31.08.2014, 22:45:07
    #38733716
Mavr747
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как при появлении новой записи в БД оповестить об этом внешнюю программу?
Marina.M, Забыл малость, подписка на сообщения:
// subscribe to a channel broadcasting between stations
oConn:Listen( "notify_"+oConn:cDataBase ) // команда серверу.
...
Рейтинг: 0 / 0
01.09.2014, 10:55:28
    #38733887
Marina.M
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как при появлении новой записи в БД оповестить об этом внешнюю программу?
buddy_ekbMarina.M,

если версия postgresql >= 9.0, то notify/listen умеют передавать и принимать дополнительное текстовое поле (payload).

а можно подробнее? Попытки найти информацию в поисковиках ничего не дали.

Я делала так:
в postgresql создавала правило:
CREATE RULE notify_some_table_update_rule AS ON UPDATE TO some_table DO NOTIFY some_table_updated;
а в Qt использовала функцию SubscribeToNotification("some_table_updated")

Можем ли мы созданным правилом передать payload(строка, где произошло изменение)? Или это надо делать с помощью триггера?
И как обработать полученное поле в проекте на Qt по оповещению из базы данных.

Если можно, то приведите пример.
...
Рейтинг: 0 / 0
01.09.2014, 15:41:59
    #38734174
buddy_ekb
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как при появлении новой записи в БД оповестить об этом внешнюю программу?
Marina.Mа можно подробнее? Попытки найти информацию в поисковиках ничего не дали.

http://www.postgresql.org/docs/current/static/sql-notify.html

Marina.MМожем ли мы созданным правилом передать payload(строка, где произошло изменение)? Или это надо делать с помощью триггера?
можете, через функцию pg_notify . пример:
Код: plsql
1.
CREATE RULE some_notify_rule AS ON UPDATE TO some_table DO SELECT pg_notify('some_channel', NEW.some_text);
...
Рейтинг: 0 / 0
01.09.2014, 16:06:22
    #38734199
Mavr747
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как при появлении новой записи в БД оповестить об этом внешнюю программу?
Marina.M,

Marina.M,
В документации Postgre:
Configure and execute a listen/notify sequence from psql:
LISTEN virtual; // Слушаем канал "virtual"
NOTIFY virtual; // Сообщаем в канал "virtual"

В моем случае вместо "virtual" имя базы данных т.е этот канал слушают только те, кто работает с базой с таким именем.
res := PQexec( ::pDB, "NOTIFY " + ::notifyChannel + ", '"+cNotify+"'" )
команда посланная станцией в канал (notifyChannel - property у класса), но может быть и просто переменная в которой имя канала (в моем случае имя базы данных с которой работает клиент). Через запятую тот самый параметр [текстовое поле (payload)]
в котором я передаю имя таблицы которая послала сообщение всем кто работает с данной базой + ":" + "действие которое сделано в таблице" ("APPEND RECORD" - вставили запись на какой-то станции, можно и номер записи передать тоже через ":". Почему двоеточие? ответ да хоть, что угодно, нам в принимающей стороне надо знать какой разделитель использован для имени таблицы (т.к. если мы с ней не работаем, то это сообщение не для нас и т.д)
PQbackendPID( ::pDB )] отдает Id процесса который сервер выделил для нашего соединения, (у каждого соединения он свой) зная его мы НЕ будем обрабатывать свои сообщения.
В петле где обрабатываются все сообщения (If PQconsumeInput(oConn:pDB) = 1 проверка если есть сообщение, взять указатель на него If ((notify := PQnotifies(oConn:pDB)) != 0) и далее если указатель не пустой....вытащить собственно сообщение и в своей процедуре сделать предписанные действия. Пришло APPEND RECORD, и если на моей станции user находится в Grid(е) в конце таблицы, то резонно показать, что появилась новая запись, если юзер не режиме редактирования поля, обновляю Grid
В Вашем случае ...DO NOTIFY some_table_updated, 'сообщение которое надо очевидно построить? оно то и есть payload'. Следующее...а Вы можете в правило параметр передать?
Вот поподробнее.
...
Рейтинг: 0 / 0
01.09.2014, 16:19:05
    #38734214
Misha Tyurin
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как при появлении новой записи в БД оповестить об этом внешнюю программу?
buddy_ekb,

рулы, суть, -- деприкейтит.
лучше уж триггер тогда.

---

а, вообще, воот
http://habrahabr.ru/post/231563/
тут писал ( mtyurin, 4 августа 2014 в 13:15# ):

"
www.hagander.net/talks/
Data driven cache invalidation (slightly updated), JDCon-East, New York City, NY, March 2011 and EuroPython 2011, Florence, Italy (+ scripts)

че-то правда у него пдфка не грузится, а
скрипты скачиваются

вот еще видео
ep2013.europython.eu/conference/talks/data-driven-cache-invalidation

суть в PGQ
"
...
Рейтинг: 0 / 0
02.09.2014, 10:46:33
    #38734661
Marina.M
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как при появлении новой записи в БД оповестить об этом внешнюю программу?
Всё это замечательно. Но хочется понять есть ли возможность применять в этом случае Qt.

Приведу алгоритм, как это реализовано сейчас в проекте Qt.

1. Создаю соединение с базой данных db.open()
2. Делаю подписку на оповещение по событию, например "update_table"
db.driver()->subscribeToNotification("update_table");
3. Соединяю сигнал notification(const QString&) с функцией обработчиком оповещения
connect(db.driver(),SIGNAL(notification(const QString&)),SLOT(функция-обработчик()));

Вот и хотелось бы кроме оповещение об изменении средствами Qt ловить и это дополнительное поле payload, если это возможно. Если нет, то разбираться уже по другим средствам.
...
Рейтинг: 0 / 0
02.09.2014, 11:20:31
    #38734701
Mavr747
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как при появлении новой записи в БД оповестить об этом внешнюю программу?
Marina.M,
Разбор:
notification(const QString&) равно команде на сервере NOTIFY имя_канала
надо:
notification(const QString&) равно команде на сервере NOTIFY имя_канала, 'то что мы передаем'
то есть:
connect(db.driver(),SIGNAL(notification(const QString&)),SLOT(функция-обработчик()));
в QString должно быть:
QString& ===>>>> " update_table, 'то что мы передаем' "
а это, как я понимаю, переменная, а не const, потому что 'то что мы передаем' будет меняться.
:)
...
Рейтинг: 0 / 0
02.09.2014, 13:58:41
    #38734923
Marina.M
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как при появлении новой записи в БД оповестить об этом внешнюю программу?
Mavr747Marina.M,
Разбор:
notification(const QString&) равно команде на сервере NOTIFY имя_канала
надо:
notification(const QString&) равно команде на сервере NOTIFY имя_канала, 'то что мы передаем'
то есть:
connect(db.driver(),SIGNAL(notification(const QString&)),SLOT(функция-обработчик()));
в QString должно быть:
QString& ===>>>> " update_table, 'то что мы передаем' "
а это, как я понимаю, переменная, а не const, потому что 'то что мы передаем' будет меняться.
:)

сигнал notification имеет вид void notification(const QString &name), если убрать const, то при исполнении ругается:
Object::connect: No such signal qPSQLDriver::notification(QString&)

получается правило создаю с передачей дополнительного поля :
CREATE RULE some_notify_rule AS ON UPDATE TO some_table DO SELECT pg_notify('update_table', 'NEW.some_text');

затем слотом получаю оповещение 'update_table', но не вытащить второй параметр.

еще вопрос в том, 'NEW.some_text' идет обязательно в кавычках, то есть как строка, а как туда записать переменную, например NEW.id? Где id - это имя поля таблицы, содержащее строчку в таблице
...
Рейтинг: 0 / 0
02.09.2014, 14:26:22
    #38734960
buddy_ekb
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как при появлении новой записи в БД оповестить об этом внешнюю программу?
Marina.Mсигнал notification имеет вид void notification(const QString &name), если убрать const, то при исполнении ругается:
Object::connect: No such signal qPSQLDriver::notification(QString&)
какая у вас версия Qt? есть мнение, что в 5.x это исправлено. ветку 4 потребуется патчить.
https://bugreports.qt-project.org/browse/QTBUG-13500

Marina.Mеще вопрос в том, 'NEW.some_text' идет обязательно в кавычках, то есть как строка, а как туда записать переменную, например NEW.id? Где id - это имя поля таблицы, содержащее строчку в таблице
можно без кавычек: достаточно, чтобы параметр был текстовым. для вашего случая, по-видимому, потребуется привести числовое значение к текстовому представлению:
Код: plsql
1.
CREATE RULE some_notify_rule AS ON UPDATE TO some_table DO SELECT pg_notify('update_table', NEW.id::text);
...
Рейтинг: 0 / 0
02.09.2014, 14:30:42
    #38734965
Marina.M
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как при появлении новой записи в БД оповестить об этом внешнюю программу?
buddy_ekb,

проект в qt 4.8.4
...
Рейтинг: 0 / 0
02.09.2014, 19:38:33
    #38735365
Mavr747
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
как при появлении новой записи в БД оповестить об этом внешнюю программу?
Marina.M,

Ой! Если "шас" не сработает, то снова в школу....
...
Рейтинг: 0 / 0
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / как при появлении новой записи в БД оповестить об этом внешнюю программу? / 22 сообщений из 22, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]