Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QSqlQuery - execution in one thread and reading the results in another
Forum Updated to NodeBB v4.3 + New Features

QSqlQuery - execution in one thread and reading the results in another

Scheduled Pinned Locked Moved Solved General and Desktop
11 Posts 3 Posters 3.3k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • N Offline
    N Offline
    napajejenunedk0
    wrote on 19 May 2018, 06:19 last edited by
    #1

    Hello all.

    Long time ago I've posted the same question in the forum, but without a single response. Now, again investigating the case, found a relevant Qt Centre forum topic where @wysota shares that:

    "I don't know how internals of QSqlQuery work but I believe that for some backends the query can still call some database functions after it is executed (e.g. when iterating over results, next results can be fetched from the database on the fly) thus accessing it from a thread different than where the query was executed could result in undefined behaviour. I would be very careful about this."
    ...
    "Today it works but from now on upon every crash or disfunction of your project you'll be wondering whether the database is causing that..."

    Thus wondering whether it is a wrong QSqlQuery usage if one thread executes the query and passes the executed QSqlQuery to another thread, so that the latter could process the results. The answer is presumably "yes" - the query keeps a cursor to the database using the QSqlDatabase instance e.g. the database connection that was created in the other thread and is designated to be used by the latter, not by the thread that processes the results.

    1 Reply Last reply
    0
    • C Offline
      C Offline
      Christian Ehrlicher
      Lifetime Qt Champion
      wrote on 19 May 2018, 06:35 last edited by
      #2

      Correct, you should not do that. Better just create a new QSqlDataBase connection in your thread and execute all there.

      Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
      Visit the Qt Academy at https://academy.qt.io/catalog

      1 Reply Last reply
      4
      • N Offline
        N Offline
        napajejenunedk0
        wrote on 19 May 2018, 10:02 last edited by
        #3

        @Christian-Ehrlicher Now looking at the sources of QSqlQuery, QSqlResult and QSqlRecord and have a question:

        • QSqlQuery is interconnected to QSqlDatabase where the latter is connected to a specific QThread instance and it is unsafe, as you mentioned, to use a single QSqlQuery instance in another thread except for the one the QSqlQuery was created at
        • Question #1: QSqlResult is interconnected with QSqlDriver and thus is it safe to pass the QSqlQuery's QSqlResult to the other thread? I presume it is not, since the QSqlResult could query the database through the database cursor that is already obtained, so that to fetch further QSqlRecords.
        • Question #2: QSqlRecord has no dependencies as far as I can see:
        class QSqlRecordPrivate
        {
        public:
            // ...
            QVector<QSqlField> fields;
            QAtomicInt ref;
        };
        

        except for QSqlField which again contains only pure data such as QString, QVariant, etc. Presumably it would be safe to read all QSqlRecords from the already executed QSqlQuery in the thread that executed the QSqlQuery and pass them to the other thread for further processing?

        1 Reply Last reply
        0
        • C Offline
          C Offline
          Christian Ehrlicher
          Lifetime Qt Champion
          wrote on 19 May 2018, 10:51 last edited by
          #4

          Once again: it may work but it must not. It can be that a driver handle it differently or anything else. Don't know what's the problem doing a new connection in the thread.

          Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
          Visit the Qt Academy at https://academy.qt.io/catalog

          N 1 Reply Last reply 19 May 2018, 10:57
          1
          • C Christian Ehrlicher
            19 May 2018, 10:51

            Once again: it may work but it must not. It can be that a driver handle it differently or anything else. Don't know what's the problem doing a new connection in the thread.

            N Offline
            N Offline
            napajejenunedk0
            wrote on 19 May 2018, 10:57 last edited by
            #5

            I already have a QSqlDatabase instance per each of both threads, but I want the query executed in the helper thread and then fetch the results in the main one, so that to improve performance.

            1 Reply Last reply
            0
            • S Offline
              S Offline
              SGaist
              Lifetime Qt Champion
              wrote on 19 May 2018, 21:09 last edited by
              #6

              Hi,

              What bottleneck do you have that requires that kind of architecture ?

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              N 1 Reply Last reply 20 May 2018, 11:22
              2
              • S SGaist
                19 May 2018, 21:09

                Hi,

                What bottleneck do you have that requires that kind of architecture ?

                N Offline
                N Offline
                napajejenunedk0
                wrote on 20 May 2018, 11:22 last edited by
                #7

                @SGaist The bottleneck are the multiple SQL queries that need to be executed while the application - a server one, should be responsive enough to answer messages received from clients. The SQL queries are now being executed on a dedicated thread where the result is being provided back to the calling thread if it was a SELECT query or a CREATE/INSERT/UPDATE where the last inserted id is the actual result. The calling thread deserializes the raw result - previously the whole QSqlQuery and now the already fetched QSqlRecords from the query, that has been executed on the helper thread if the query was a SELECT one. As @Christian-Ehrlicher already said it is prohibited to use any of the QSql-related classes across threads, but looking at the Qt sources, only the classes QSqlDatabase, QSqlDriver, QSqlQuery and QSqlResult are dangerous and should be avoided in multi-thread scenarios where QSqlRecord and its constituent QSqlFields are nothing more but data containers and are safe enough to be created by one and used by another thread. Also the documentation concerning Qt SQL module and thread usage mentions:
                "A connection can only be used from within the thread that created it. Moving connections between threads or creating queries from a different thread is not supported.
                In addition, the third party libraries used by the QSqlDrivers can impose further restrictions on using the SQL Module in a multithreaded program. Consult the manual of your database client for more information"

                Despite the scarce documentation about thread usage with the Qt SQL module, the only limitations I see is that it is unsafe to pass around QSqlDatabase and QSqlQuery between threads. Also, @JKSH has given an example for a correct database usage with a dedicated database thread (which is exactly the scenario at hand). Found this forum topic just now. He gives as an example (and presumably recommends) using QList< QSqlRecord > as a transport of the output data coming from executed SELECT queries.
                Again, it is possible to avoid the usage of QSqlRecord instances across threads, by creating a minified replica of the QSqlRecord e.g. a mapping between field/column name -> value but to me it is unworthy.

                1 Reply Last reply
                0
                • C Offline
                  C Offline
                  Christian Ehrlicher
                  Lifetime Qt Champion
                  wrote on 20 May 2018, 12:09 last edited by
                  #8

                  I still don't understand what's the problem in doing the exec and fetch in one thread and passing the result back to the main thread thereafter. But do what you like but don't complain when something will not work with a new Qt version (or another SQL driver) later on.

                  Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                  Visit the Qt Academy at https://academy.qt.io/catalog

                  N 1 Reply Last reply 21 May 2018, 06:50
                  1
                  • C Christian Ehrlicher
                    20 May 2018, 12:09

                    I still don't understand what's the problem in doing the exec and fetch in one thread and passing the result back to the main thread thereafter. But do what you like but don't complain when something will not work with a new Qt version (or another SQL driver) later on.

                    N Offline
                    N Offline
                    napajejenunedk0
                    wrote on 21 May 2018, 06:50 last edited by
                    #9

                    @Christian-Ehrlicher said in QSqlQuery - execution in one thread and reading the results in another:

                    doing the exec and fetch

                    I am doing exactly this now in the database thread: exec + extracting all resultant QSqlRecords from the QSqlQuery as you suggested:

                    Correct, you should not do that. Better just create a new QSqlDataBase connection in your thread and execute all there.

                    What I wasn't doing before in the database thread aside the execution of the QSqlQuery is the extraction of the result from the QSqlQuery in case it is a select one e.g. fetching all QSqlRecords. The last question at hand was whether QSqlRecord is safe enough to be passed between threads.

                    1 Reply Last reply
                    0
                    • C Offline
                      C Offline
                      Christian Ehrlicher
                      Lifetime Qt Champion
                      wrote on 21 May 2018, 07:44 last edited by
                      #10

                      From the current source it looks ok but as I said above - I would not rely on it.
                      And creating a QSqlRecord for every returned row is not cheap (and mostly useless). Just convert your data in the format you need (or return QVariants) in your thread and return those values.

                      Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                      Visit the Qt Academy at https://academy.qt.io/catalog

                      N 1 Reply Last reply 21 May 2018, 10:24
                      0
                      • C Christian Ehrlicher
                        21 May 2018, 07:44

                        From the current source it looks ok but as I said above - I would not rely on it.
                        And creating a QSqlRecord for every returned row is not cheap (and mostly useless). Just convert your data in the format you need (or return QVariants) in your thread and return those values.

                        N Offline
                        N Offline
                        napajejenunedk0
                        wrote on 21 May 2018, 10:24 last edited by
                        #11

                        @Christian-Ehrlicher Ok, thanks.

                        1 Reply Last reply
                        0

                        1/11

                        19 May 2018, 06:19

                        • Login

                        • Login or register to search.
                        1 out of 11
                        • First post
                          1/11
                          Last post
                        0
                        • Categories
                        • Recent
                        • Tags
                        • Popular
                        • Users
                        • Groups
                        • Search
                        • Get Qt Extensions
                        • Unsolved