Results 1 to 9 of 9

Thread: SQL query does not work every time

  1. #1
    Join Date
    Sep 2012
    Posts
    34
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Windows

    Default SQL query does not work every time

    I've got a server that uses SQL to store data sent by client. There is a support for several simultaneous clients and I've implemented "lock" field to the database so that other clients won't be able to update the same record at the same time. So client uses this field when taking the record into edit state. Client can reset this field by sending one specific command which starts a function at the server side that does the trick. Problem is that the release command executed in the release function seem not to work every time because it gives following error occasionally: No query Unable to fetch row. How is this possible if the very same command is used every time?


    The release function:
    Qt Code:
    1. void serverthread::release_lock(QSslSocket *ptr_socket)
    2. {
    3. emit thread_trace_in_main("-> release_lock(QSslSocket *ptr_socket)", false); // this signal is just for tracing purposes
    4.  
    5. QSqlQuery query;
    6.  
    7. if (!db.open()) {
    8. emit thread_trace_in_main("ERROR: "+DB_NAME, true);
    9. ptr_socket->write("ERROR\n");
    10. emit thread_errors();
    11. return;
    12. }
    13.  
    14. QString command="";
    15.  
    16. command= QString("UPDATE init SET locked='not_locked' WHERE locked='%1'").arg(client);
    17. emit thread_trace_in_main(command, false);
    18. query.prepare( command);
    19. if (!query.exec()) {
    20. emit thread_trace_in_main("UPDATE ERROR -> "+query.lastError().text(), false);
    21. ptr_socket->write("ERROR\n");
    22. }
    23. command= QString("UPDATE client SET locked='not_locked' WHERE locked='%1'").arg(client);
    24. emit thread_trace_in_main(command, false);
    25. query.prepare( command);
    26. if (!query.exec()) {
    27. emit thread_trace_in_main("UPDATE ERROR -> "+query.lastError().text(), false);
    28. ptr_socket->write("ERROR\n");
    29. }
    30. command= QString("UPDATE changes SET locked='not_locked' WHERE locked='%1'").arg(client);
    31. emit thread_trace_in_main(command, false);
    32. query.prepare( command);
    33. if (!query.exec()) {
    34. emit thread_trace_in_main("UPDATE ERROR -> "+query.lastError().text(), false);
    35. ptr_socket->write("ERROR\n");
    36. }
    37.  
    38. ptr_socket->write("READY\n");
    39. }
    To copy to clipboard, switch view to plain text mode 

    Debug log showing the occasional problem:
    Qt Code:
    1. ( 09:02:13 ) -> void serverthread::wait_for_request()
    2. ( 09:02:14 ) REQ: RELEASE
    3. ( 09:02:14 ) -> release_lock(QSslSocket *ptr_socket)
    4. ( 09:02:14 ) UPDATE init SET locked='not_locked' WHERE locked='Teppo Testaaja'
    5. ( 09:02:14 ) UPDATE client SET locked='not_locked' WHERE locked='Teppo Testaaja'
    6. ( 09:02:14 ) UPDATE changes SET locked='not_locked' WHERE locked='Teppo Testaaja'
    7. ( 09:02:14 ) -> void serverthread::wait_for_request()
    8. ( 09:02:39 ) REQ: RELEASE
    9. ( 09:02:39 ) -> release_lock(QSslSocket *ptr_socket)
    10. ( 09:02:39 ) UPDATE init SET locked='not_locked' WHERE locked='Teppo Testaaja'
    11. ( 09:02:39 ) UPDATE ERROR -> No query Unable to fetch row
    12. ( 09:02:39 ) UPDATE client SET locked='not_locked' WHERE locked='Teppo Testaaja'
    13. ( 09:02:39 ) UPDATE ERROR -> No query Unable to fetch row
    14. ( 09:02:39 ) UPDATE changes SET locked='not_locked' WHERE locked='Teppo Testaaja'
    15. ( 09:02:39 ) UPDATE ERROR -> No query Unable to fetch row
    16. ( 09:02:39 ) -> void serverthread::wait_for_request()
    17. ( 09:02:40 ) REQ: RELEASE
    18. ( 09:02:40 ) -> release_lock(QSslSocket *ptr_socket)
    19. ( 09:02:40 ) UPDATE init SET locked='not_locked' WHERE locked='Teppo Testaaja'
    20. ( 09:02:40 ) UPDATE client SET locked='not_locked' WHERE locked='Teppo Testaaja'
    21. ( 09:02:40 ) UPDATE changes SET locked='not_locked' WHERE locked='Teppo Testaaja'
    22. ( 09:02:40 ) -> void serverthread::wait_for_request()
    23. ( 09:02:42 ) REQ: RELEASE
    24. ( 09:02:42 ) -> release_lock(QSslSocket *ptr_socket)
    25. ( 09:02:42 ) UPDATE init SET locked='not_locked' WHERE locked='Teppo Testaaja'
    26. ( 09:02:42 ) UPDATE client SET locked='not_locked' WHERE locked='Teppo Testaaja'
    27. ( 09:02:42 ) UPDATE changes SET locked='not_locked' WHERE locked='Teppo Testaaja'
    28. ( 09:02:42 ) -> void serverthread::wait_for_request()
    To copy to clipboard, switch view to plain text mode 

    As you can see the second RELEASE request fails due to the SQL failure. When the failure happens it seems that all the three UPDATE commands fail. Any ideas? Failure rate is about 1 or 2 out of 10.

  2. #2
    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: SQL query does not work every time

    query should be defined AFTER opening DB connection and should looks like :
    Qt Code:
    1. QSqlQuery query(db);
    To copy to clipboard, switch view to plain text mode 

  3. #3
    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: SQL query does not work every time

    If you are using threads -- are you aware of the rules governing the use of SQL with threads in Qt?
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  4. #4
    Join Date
    Sep 2012
    Posts
    34
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: SQL query does not work every time

    Quote Originally Posted by Lesiok View Post
    query should be defined AFTER opening DB connection and should looks like :
    Qt Code:
    1. QSqlQuery query(db);
    To copy to clipboard, switch view to plain text mode 
    I found the problem after you mentioned opening DB connection. Actually the connection was already opened earlier in my initialization function so basically I was trying to open it again every time the release function was called. Instead of opening the connection my meaning was to check that the connection is fine. So with the following lines it seems to be working:

    Qt Code:
    1. if (!db.isOpen()) {
    2. emit thread_trace_in_main("ERROR: "+DB_NAME, true);
    3. ptr_socket->write("ERROR\n");
    4. emit thread_errors();
    5. return;
    6. }
    To copy to clipboard, switch view to plain text mode 

    wysota, I kind of get a feeling that I do not know principles of using SQL in threads. Could you light me up a bit?


    Thanks again for your time!

  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: SQL query does not work every time

    If you have multiple threads, you can only use a particular database connection object in the same thread in which you created the connection. So if you want to use the database from three threads, you need three separate connections. Also you can't open the connection in thread A and use it in thread B (even if you're not using it in thread A anymore). Otherwise you'll start getting strange results, like losing rows or query results.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  6. #6
    Join Date
    Sep 2012
    Posts
    34
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: SQL query does not work every time

    Ok, that sounds logical. In my case I'm creating the database connection in a new thread whenever it is started so that should do the trick.

    However I'm not sure if this is due to threads but for some reason if the client is closed (or process killed), the DB connection cannot be opened again. Wonder why?

    Whenever the client is closed, I use db.close() but it seems that this is not enough. Or as said the other option is that I'm not making this correctly with threads. Btw, currently the DB is created like this:

    Qt Code:
    1. #include "serverthread.h"
    2. #include <QtGui>
    3. #include <QtNetwork>
    4. QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
    To copy to clipboard, switch view to plain text mode 

  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: SQL query does not work every time

    The database may fail to open if the killed process did not release a lock on the sqlite file. Are you also using QSqlDatabase::removeDatabase()?
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  8. #8
    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: SQL query does not work every time

    Carefully read the description of the QSqlDatabase::addDatabase method. You have to use the second parameter.

  9. #9
    Join Date
    Sep 2012
    Posts
    34
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: SQL query does not work every time

    Thanks, I was not using the connection name parameter (neither QSqlDatabase::removeDatabase()) so each time client contacted again it tried to use the same default connection and it failed. Now I'm using clients username to differentiate the database connection name. Seems to work.

    Cheers guys!

Similar Threads

  1. Replies: 2
    Last Post: 16th October 2011, 07:53
  2. C++/Qt, remote work, part-time
    By mannaz in forum Jobs
    Replies: 3
    Last Post: 15th June 2011, 17:09
  3. setValue of ScrollBar Don't work at first time
    By sergio87 in forum Qt Programming
    Replies: 8
    Last Post: 8th June 2011, 10:00
  4. Replies: 6
    Last Post: 18th August 2010, 12:52
  5. Replies: 0
    Last Post: 12th August 2010, 16:05

Tags for this Thread

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.