Results 1 to 11 of 11

Thread: Qt doesn't detect PostgreSQL asynchronous notifications in same instance

  1. #1
    Join Date
    Jul 2008
    Location
    Spain
    Posts
    23
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Qt doesn't detect PostgreSQL asynchronous notifications in same instance

    I have created a rule in a PosgreSQL table to execute it when inserting a row.

    It calls "NOTIFY myNotify" and works fine when I insert a row with an INSERT SQL command. Qt detects the notification well.

    When I insert a row in a table view that depends on a table model, the rule works fine, but Qt doesn't detect the notification.

    Here is a sample main function:
    Qt Code:
    1. #include <QApplication>
    2. #include <QSqlDriver>
    3. #include "myClass.hpp"
    4.  
    5. int main(int argc, char *argv[]) {
    6. QApplication aplication(argc, argv);
    7.  
    8. // Open conection to database
    9. QSqlDatabase bd(QSqlDatabase::addDatabase("QPSQL"));
    10. bd.setHostName("localhost");
    11. bd.setDatabaseName("myDB");
    12. bd.open("postgres", "postgres");
    13.  
    14. // Load data in the table
    15. QTableView myTV;
    16. QSqlRelationalTableModel myModel(&myTV, bd);
    17. myModel.setEditStrategy(QSqlTableModel::OnManualSubmit);
    18. myModel.setTable("myTable");
    19.  
    20. // Show table with the data from database
    21. myModel.select();
    22. myTV.setModel(&myModel);
    23. myTV.show();
    24.  
    25. // Create the object with the slot to save changes to database
    26. TmyClass myObject(0, &myModel);
    27.  
    28. // Subscribe and define the treatment for the notification thrown when updating a field
    29. bd.driver()->subscribeToNotification("modified_row");
    30. QObject::connect((QObject*)bd.driver(), SIGNAL(notification(const QString&)), (QObject*)&myObject, SLOT(myNotifyHandler(const QString&)));
    31.  
    32. return aplication.exec();
    33. }
    To copy to clipboard, switch view to plain text mode 

    The class to save changes manually:
    Qt Code:
    1. #ifndef TMYCLASS
    2. #define TMYCLASS
    3.  
    4. #include <QtCore/QDebug>
    5. #include <QtGui/QTableView>
    6. #include <QtSql/QSqlError>
    7. #include <QtSql/QSqlRelationalDelegate>
    8.  
    9. class TmyClass : public QObject
    10. {
    11. Q_OBJECT
    12.  
    13. public:
    14. TmyClass(QObject *parent, QSqlRelationalTableModel *oneModel);
    15.  
    16. public slots:
    17. void mySave(const QModelIndex &a, const QModelIndex &b);
    18. void myNotifyHandler(const QString &notification);
    19.  
    20. private:
    21. };
    22.  
    23. #endif
    24.  
    25. TmyClass::TmyClass(QObject *parent, QSqlRelationalTableModel *oneModel): QObject(parent), m_model(oneModel)
    26. {
    27. // When something changes, call the slot mySave
    28. connect(m_model, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)), this, SLOT(mySave(const QModelIndex&, const QModelIndex&)));
    29. }
    30.  
    31.  
    32. void TmyClass::mySave(const QModelIndex &a, const QModelIndex &b)
    33. {
    34. if(!m_model->submitAll())
    35. {
    36. qDebug()<<"Error when submitting:"<<m_model->lastError().text();
    37. }
    38. }
    39.  
    40.  
    41. void TmyClass::myNotifyHandler(const QString &notification)
    42. {
    43. qDebug()<<"Detected notification from PostgreSQL: "<<notification;
    44. }
    To copy to clipboard, switch view to plain text mode 

    PostgreSQL sample database dump (is a very simple table, the important detail is "CREATE RULE "myRule" AS ON UPDATE TO "myTable" DO NOTIFY modified_row;"):
    Qt Code:
    1. SET client_encoding = 'UTF8';
    2. SET standard_conforming_strings = off;
    3. SET check_function_bodies = false;
    4. SET client_min_messages = warning;
    5. SET escape_string_warning = off;
    6. SET search_path = public, pg_catalog;
    7. SET default_tablespace = '';
    8. SET default_with_oids = false;
    9. CREATE TABLE "myTable" (
    10. "ID" integer NOT NULL,
    11. name text
    12. );
    13. ALTER TABLE public."myTable" OWNER TO postgres;
    14. CREATE SEQUENCE "myTable_ID_seq"
    15. INCREMENT BY 1
    16. NO MAXVALUE
    17. NO MINVALUE
    18. CACHE 1;
    19. ALTER TABLE public."myTable_ID_seq" OWNER TO postgres;
    20. ALTER SEQUENCE "myTable_ID_seq" OWNED BY "myTable"."ID";
    21. SELECT pg_catalog.setval('"myTable_ID_seq"', 3, true);
    22. ALTER TABLE "myTable" ALTER COLUMN "ID" SET DEFAULT nextval('"myTable_ID_seq"'::regclass);
    23. COPY "myTable" ("ID", name) FROM stdin;
    24. 1 One
    25. 2 Two
    26. 3 Three
    27. \.
    28.  
    29. ALTER TABLE ONLY "myTable" ADD CONSTRAINT pk PRIMARY KEY ("ID");
    30. CREATE RULE "myRule" AS ON UPDATE TO "myTable" DO NOTIFY modified_row;
    31. REVOKE ALL ON SCHEMA public FROM PUBLIC;
    32. REVOKE ALL ON SCHEMA public FROM postgres;
    33. GRANT ALL ON SCHEMA public TO postgres;
    34. GRANT ALL ON SCHEMA public TO PUBLIC;
    To copy to clipboard, switch view to plain text mode 

    Some links I have read:
    QSqlDriver notifications
    Blog about asynchronous database event notifications
    Asynchronous notifications in PostgreSQL
    Attached Files Attached Files
    Last edited by Auryn; 28th November 2008 at 12:40. Reason: add code
    Auryn
    Starting to learn the world of Qt

  2. #2
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Qt doesn't detect PostgreSQL asyncronous notification events when using QTableVie

    If you modify the model, the changes are not saved to the database immediately. They are instead cached in the model. To force a flush to the database, call submitAll() on the model.

  3. #3
    Join Date
    Jul 2008
    Location
    Spain
    Posts
    23
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Qt doesn't detect PostgreSQL asyncronous notification events when using QTableVie

    Yes, I do the submitAll in a slot, but it doesn't detect the notify.

    With my example, if I execute directly in pgadmin3:
    Qt Code:
    1. UPDATE "myTable" SET name='changed' WHERE "ID"=1;
    To copy to clipboard, switch view to plain text mode 
    My example shows what I wanted:
    Detected notification from PostgreSQL: "modified_row"
    Thank you very much
    Auryn
    Starting to learn the world of Qt

  4. #4
    Join Date
    Jul 2008
    Location
    Spain
    Posts
    23
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Qt doesn't detect PostgreSQL asyncronous notification events when using QTableVie

    I have tested with two instances of my example at the same time, and one detects the update done in the other.
    Then, one instance can't detect its own database modifications.
    Any idea?
    Auryn
    Starting to learn the world of Qt

  5. #5
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Qt doesn't detect PostgreSQL asyncronous notification events when using QTableVie

    Are you sure the changes are submitted to the database?

  6. #6
    Join Date
    Jul 2008
    Location
    Spain
    Posts
    23
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Qt doesn't detect PostgreSQL asynchronous notifications in same instance

    Yes, I am sure the changes are submitted to the database.
    Auryn
    Starting to learn the world of Qt

  7. #7
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Qt doesn't detect PostgreSQL asynchronous notifications in same instance

    Are you sure postgres sends notifications to the same connection that caused the modification? Could you verify that with a simple program using PSQL API directly?

  8. #8
    Join Date
    Jul 2008
    Location
    Spain
    Posts
    23
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Qt doesn't detect PostgreSQL asynchronous notifications in same instance

    I have used psql to listen for the notification:
    Qt Code:
    1. LISTEN modified_row;
    To copy to clipboard, switch view to plain text mode 

    It works well like that:
    Qt Code:
    1. myDB=# SELECT * FROM "myTable";
    2. ID | name
    3. ----+-------
    4. 1 | Tom
    5. 2 | Peter
    6. 3 | John
    7. (3 rows)
    8.  
    9. myDB=# UPDATE "myTable" SET name='Mike' WHERE "ID"=3;
    10. UPDATE 1
    11. Asynchronous notification «modified_row» received from server process with PID 13043.
    12. myDB=# SELECT * FROM "myTable";
    13. ID | name
    14. ----+-------
    15. 1 | Tom
    16. 2 | Peter
    17. 3 | Mike
    18. (3 rows)
    To copy to clipboard, switch view to plain text mode 
    Auryn
    Starting to learn the world of Qt

  9. #9
    Join Date
    Jul 2008
    Location
    Spain
    Posts
    23
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Qt doesn't detect PostgreSQL asynchronous notifications in same instance

    So notifications work:
    - when using psql. For example, when writing in the psql window: "Update..." then the Qt app gets informed of the change.
    - when doing the test of: having two instances of my example program at the same time (one detects the update done in the other).

    But it does not work when:
    - One program can't detect the modifications done within the same program.

    But maybe it's a minor change that I should do.
    Auryn
    Starting to learn the world of Qt

  10. #10
    Join Date
    Apr 2010
    Posts
    2
    Qt products
    Qt4

    Default Re: Qt doesn't detect PostgreSQL asynchronous notifications in same instance

    hi,

    I found the same problem. It should be a QT problem (bug), the interesting part of all this is that, when the same application "NOTIFY" it self, all notifications are buffered, by the driver, but the receiver's slot is not called until a "NOTIFY" from other process occur.

    Qt Code:
    1. class Test : public QObject
    2. {
    3. Q_OBJECT
    4.  
    5. public slots:
    6. void receiver()
    7. {
    8. qDebug("signal emitted");
    9. }
    10.  
    11. public:
    12. Test(){};
    13. };
    14. int main(int argc, char *argv[])
    15. {
    16. QCoreApplication a(argc, argv);
    17. initDB();
    18. Test r;
    19.  
    20. if(!db.driver()->subscribeToNotification("aaaa"))
    21. qDebug( qPrintable(db.driver()->lastError().databaseText()) );
    22.  
    23. QObject::connect((QObject*)db.driver(), SIGNAL(notification(const QString&)), (QObject*)&r, SLOT(receiver()) );
    24.  
    25.  
    26. QSqlQuery q0("NOTIFY aaaa;");
    27. q0.exec();
    28. QSqlQuery q1("NOTIFY aaaa;");
    29. q1.exec();
    30.  
    31. return a.exec();
    32. }
    To copy to clipboard, switch view to plain text mode 

    In this case, when some other process execute "NOTIFY aaaa;" the "receiver()" slot will be called 3 times.

    Any suggestions?

  11. #11
    Join Date
    Mar 2008
    Location
    Kraków, Poland
    Posts
    1,536
    Thanked 284 Times in 279 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Qt doesn't detect PostgreSQL asynchronous notifications in same instance

    Renew this thread.
    Problem occurs on Linux and NOT occurs on Windows. In attachment simple test application.
    Attached Files Attached Files

Similar Threads

  1. How to Compile VTKDesigner2 with Qt?
    By alfredoaal in forum Newbie
    Replies: 0
    Last Post: 5th September 2008, 06:34

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.