Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Special Interest Groups
  3. C++ Gurus
  4. Deserializing QSqlQuery using submethod in efficient way

Deserializing QSqlQuery using submethod in efficient way

Scheduled Pinned Locked Moved Unsolved C++ Gurus
c++ qtmysql
6 Posts 2 Posters 870 Views
  • 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.
  • B Offline
    B Offline
    bwylegly
    wrote on last edited by bwylegly
    #1

    My data access layer uses interface SQLAdapter, which provides two methods:

    • deserialize(),
    • deserializeAll()

    I'd like to use deserialize in deserializeAll method.
    Function, which uses both of those has access to QSqlQuery object.

    At this point, I am not really sure how to implement deserialize() method. According to what i've found in documentation, before reading values from db, we must use ex. next() or first().

    Currently, after executing QSqlQuery object, i check whether query isValid(). After that, i next() query, and pass it to deserialize() or deserializeAll() depending on number of records (deserializeAll calls deserialize for every record).

    std::unique_ptr<T> T::deserialize(QSqlQuery& row);
    std::vector<std::unique_ptr<T>> T::deserializeAll(QSqlQuery& result);
    

    First problem is that, after passing QSqlQuery to deserialize, isActive() method returns false, but im still able to read values from it.
    I cannot understand this behaviour.

    Secondly, im not sure if passing QSqlQuery is "elegant" way, so I've tried to modify deserialize so it uses QSqlRecord:

    std::unique_ptr<T> T::deserialize(const QSqlRecord& row)
    

    But if I do so, I cannot read any values from record. Each field isNull().
    Moreover, documentation says that we should use value() with QSqlQuery instead of QSqlRecord.

    Could somebody point out what am I missing about classes mentioned above, and provide me with elegant and correct way of implementing those methods?
    Thanks in advance.

    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi,

      Can you show exactly how you are using that class including the querying part ?

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

      1 Reply Last reply
      0
      • B Offline
        B Offline
        bwylegly
        wrote on last edited by bwylegly
        #3

        @SGaist
        Hi,
        firstly, I prepare query in DAO class

        virtual std::unique_ptr<T> get(const int& arg) {
            std::string query = "SELECT * FROM ";
            query.append(tableName).append(" WHERE id = ");
            query.append(std::to_string(arg));
        
            std::unique_ptr<QSqlQuery> resultPtr  = SQLManager::execute(query.c_str());
            if (resultPtr != nullptr) {
                QSqlQuery result = *(resultPtr.get());
                if(result.isActive()){
                    T person;
                    result.first();
                    std::unique_ptr<T> ptr = person.deserialize(result);
                    SQLManager::finish(result);
                    return ptr;
                }
            }
            return nullptr;
        };
        

        I execute it in SQLManager class:

        static std::unique_ptr<QSqlQuery> execute(const char* query) {
            establishConnection();
        
            if (db.isOpen()) {
                QSqlQuery sqlQuery;
        
                if ( sqlQuery.exec(query) != 1) {
                    db.close();
                    return nullptr;
                }
                else {
                    db.close();
                    return std::make_unique<QSqlQuery>(sqlQuery);
                }
            }
            return nullptr;
        }
        

        And as you can see in first bit of code, i deserialize it using, for example, Patient class:

        std::unique_ptr<Patient> Patient::deserialize(QSqlQuery& row) {
        
            if(row.isValid()){
        
                std::string pesel, surname, firstName, secondName;
                int doctorId;
        
                pesel = row.value(1).toString().toStdString();
                surname = row.value(2).toString().toStdString();
                firstName = row.value(3).toString().toStdString();
                secondName = row.value(4).toString().toStdString();
        
                if (row.value(5).isNull()) {
                   doctorId = -1;
                }
                else {
                   doctorId = row.value(5).toInt();
                }
        
                return std::make_unique<Patient>(pesel, surname, firstName, secondName, doctorId);
        
            }else{
                return nullptr;
            }
            
        }
        

        And finally, all of that is being used in deserialize all:

        std::vector<std::unique_ptr<Patient>> Patient::deserializeAll(QSqlQuery& result) {
        	
            std::vector<std::unique_ptr<Patient>> patients;
        
            if(result.isActive()){
        
                while(result.next()){
                     patients.push_back(deserialize(result));
                }
            }
        
            return patients;
        }
        
        SQLManager::finish(query);
        

        method is responsible for clearing query only (I have moved it into temporary function for now)

        1 Reply Last reply
        0
        • SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on last edited by
          #4

          Why are you closing the database connection before processing your query ?

          Out of curiosity, why use all these unique_ptr to manage QSqlQuery objects ?

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

          1 Reply Last reply
          1
          • B Offline
            B Offline
            bwylegly
            wrote on last edited by
            #5

            About db connection:
            When I started to use QT sql library I thought that QSqlQuery is independent from db connection - its a mistake i haven't fixed yet.

            Is this the reason for QSqlQuery::isActive() to fail?
            About unique_ptrs:
            Previously i was using Mysql C Connector with VS in which i worked with pointers on query result sets, so when I changed IDE to QT i thought that it can stay like that for now, until i get done with connecting, and "translating" code to QT.

            Btw - Is QSqlQuery::clear() called when unique_ptr<QSqlQuery> goes out of scope?

            1 Reply Last reply
            0
            • SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on last edited by
              #6

              No it's not, you can see that with its constructors that take a QSqlDatabase parameter.

              No clear is not called, the destructor is.

              There's no need to create QSqlQuery objects on the heap.

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

              1 Reply Last reply
              1

              • Login

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