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 in Qt6: in-place vs prepared
Qt 6.11 is out! See what's new in the release blog

QSqlQuery in Qt6: in-place vs prepared

Scheduled Pinned Locked Moved Unsolved General and Desktop
qsqlqueryqsqlquerymodelqtableview
26 Posts 5 Posters 9.3k Views 2 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.
  • D Offline
    D Offline
    dviktor
    wrote on last edited by dviktor
    #13

    If I change my basic SQL query statement (the first line of it) from:
    "SELECT DISTINCT e.id, e.name, e.type, v.ts, v.upto, v.d_left "
    to:
    "SELECT DISTINCT e.id, e.name, e.type, DATE_FORMAT(v.ts, '%d.%m.%Y'), DATE_FORMAT(v.upto, '%d.%m.%Y'), v.d_left "
    (remember that I still use plain QSqlQueryModel so no custom data conversions involved) then all works fine!
    querybug2.png

    So, it looks like QSqlQueryModel misbehaves somehow in connection with QTableView when some of the columns are of QDate type

    1 Reply Last reply
    0
    • Christian EhrlicherC Offline
      Christian EhrlicherC Offline
      Christian Ehrlicher
      Lifetime Qt Champion
      wrote on last edited by
      #14

      Your test still does not create and fill the table. Fix it if you want help from me.

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

      D 1 Reply Last reply
      0
      • Christian EhrlicherC Christian Ehrlicher

        Your test still does not create and fill the table. Fix it if you want help from me.

        D Offline
        D Offline
        dviktor
        wrote on last edited by dviktor
        #15

        @Christian-Ehrlicher I've made direct dump of my test database. You can quickly feed it to the MariaDB with:
        cat dbtest.sql | mariadb -u root -p -D dbtest
        assuming dbtest database already created

        PS: added '05' strings to make search return the same results
        PPS: '05' was used as search string in my MRE

        1 Reply Last reply
        0
        • Christian EhrlicherC Offline
          Christian EhrlicherC Offline
          Christian Ehrlicher
          Lifetime Qt Champion
          wrote on last edited by
          #16

          This is working fine for me:

          #include <QtSql>
          #include <QtWidgets>
          
          int main(int argc, char* argv[])
          {
              QApplication a(argc, argv);
              QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
              db.setDatabaseName("testdb");
              db.setUserName("");
              db.setPassword("");
              db.setHostName("");
              db.setConnectOptions("MYSQL_OPT_SSL_VERIFY_SERVER_CERT=FALSE");
              if (!db.open()) {
                  qDebug() << db.lastError();
                  return 1;
              }
              QSqlQuery query;
              query.exec("DROP TABLE IF EXISTS test");
              if (!query.exec("CREATE TABLE test (id int, ts date)")) {
                  qDebug() << query.lastError();
                  return 1;
              }
              QString insertSql1 = "INSERT INTO test (id, ts) VALUES (1, now())";
              if (!query.exec(insertSql1)) {
                  qDebug() << query.lastError();
                  return 1;
              }
              QTableView tv1;
              auto model1 = new QSqlQueryModel;
              model1->setQuery(QSqlQuery("SELECT * FROM test WHERE id = 1"));
              tv1.setModel(model1);
              tv1.show();
          
              QTableView tv2;
              auto model2 = new QSqlQueryModel;
              QSqlQuery q;
              q.prepare("SELECT * FROM test WHERE id = :id");
              q.bindValue(":id", 1);
              q.exec();
              model2->setQuery(std::move(q));
              tv2.setModel(model2);
              tv2.show();
          
              int ret = a.exec();
              query.exec("DROP TABLE IF EXISTS test");
              db.close();
              return ret;
          }
          

          Please provide a minimal, compilable example to reproduce your problem.

          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
          1
          • D Offline
            D Offline
            dviktor
            wrote on last edited by
            #17

            I've already attached all source code files as well as database dump. I can surely reproduce the problem described on attached dataset

            1 Reply Last reply
            0
            • Christian EhrlicherC Offline
              Christian EhrlicherC Offline
              Christian Ehrlicher
              Lifetime Qt Champion
              wrote on last edited by
              #18

              I told you what I need and also showed you that it works correctly so... Prove me wrong

              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
              0
              • D Offline
                D Offline
                dviktor
                wrote on last edited by
                #19

                I don't argue that it may work on this simplest two-column example without any issues but that's not my case. My SQL query is a bit more sophisticated and includes JOINs as well as calculated columns (with MAX, DATEDIFF etc). Checking with bare SQL request via mariadb command line client or phpMyAdmin console shows that the query line itself is ok - I get all expected rows and columns.

                And as it shown on the screenshots above the problem goes away if I wrap DATE-typed columns with DATE_FORMAT so I effectively get string objects instead of date. So that's why I've decided it's a bug somewhere in Qt. I've also prepared minimal database sample which exposes erratic behavior. Moreover, the database itself may be provided by third-party service and not by means of Qt-aided creation. Who knows - may be there are some difference in a way database were prepared.

                JonBJ 1 Reply Last reply
                0
                • D dviktor

                  I don't argue that it may work on this simplest two-column example without any issues but that's not my case. My SQL query is a bit more sophisticated and includes JOINs as well as calculated columns (with MAX, DATEDIFF etc). Checking with bare SQL request via mariadb command line client or phpMyAdmin console shows that the query line itself is ok - I get all expected rows and columns.

                  And as it shown on the screenshots above the problem goes away if I wrap DATE-typed columns with DATE_FORMAT so I effectively get string objects instead of date. So that's why I've decided it's a bug somewhere in Qt. I've also prepared minimal database sample which exposes erratic behavior. Moreover, the database itself may be provided by third-party service and not by means of Qt-aided creation. Who knows - may be there are some difference in a way database were prepared.

                  JonBJ Offline
                  JonBJ Offline
                  JonB
                  wrote on last edited by JonB
                  #20

                  @dviktor
                  I looked at your "minimal" repro. The queries are horrendously long and complex, and require many tables with many columns. If I were you and I wanted help/someone to look at it I would spend my time reducing to an absolute minimum, e.g. does it require a JOIN at all, does it show up with one JOIN, do I really need a calculated column, do I need MAX() or other "aggregate", does it matter whether a column is DATE versus DATETIME, does the WHERE clause matter, etc. I would hope to produce the absolute minimum code and database where I could say: "if you run this query it works fine but as soon as I make just this one little change it goes wrong". Up to you.

                  1 Reply Last reply
                  0
                  • T Offline
                    T Offline
                    Tiziano Bacocco
                    wrote last edited by
                    #21

                    I'm encountering same problem, below is a simpler test case

                    +----------+----------+------+-----+---------+----------------+
                    | Field    | Type     | Null | Key | Default | Extra          |
                    +----------+----------+------+-----+---------+----------------+
                    | id       | int(11)  | NO   | PRI | NULL    | auto_increment |
                    | apertura | datetime | NO   |     | NULL    |                |
                    | chiusura | datetime | NO   |     | NULL    |                |
                    +----------+----------+------+-----+---------+----------------+
                    

                    This works

                    QSqlQuery query(db);
                    
                        if (!query.exec("SELECT * FROM giornate WHERE id = 56")) {
                            qCritical() << "Query failed:";
                            qCritical() << query.lastError().text();
                            return 1;
                        }
                    
                        while (query.next()) {
                            int id = query.value("id").toInt();
                    
                            // Qt automatically converts SQL DATETIME to QDateTime
                            QDateTime apertura = query.record().value("apertura").value<QDateTime>();
                            QDateTime chiusura = query.value("chiusura").toDateTime();
                    
                            qDebug().noquote()
                            << QString("ID: %1").arg(id);
                    
                            qDebug().noquote()
                            << QString("  apertura: %1")
                            .arg(apertura.toString(Qt::ISODate));
                    
                            qDebug().noquote()
                            << QString("  chiusura: %1")
                            .arg(chiusura.toString(Qt::ISODate));
                    
                            qDebug() << "";
                        }
                    

                    This doesn't

                    QSqlQuery query(db);
                        query.prepare("SELECT * FROM giornate WHERE id = ?");
                        query.bindValue(0,56);
                        if (!query.exec()) {
                            qCritical() << "Query failed:";
                            qCritical() << query.lastError().text();
                            return 1;
                        }
                    
                        while (query.next()) {
                            int id = query.value("id").toInt();
                    
                            // Qt automatically converts SQL DATETIME to QDateTime
                            QDateTime apertura = query.record().value("apertura").value<QDateTime>();
                            QDateTime chiusura = query.value("chiusura").toDateTime();
                    
                            qDebug().noquote()
                            << QString("ID: %1").arg(id);
                    
                            qDebug().noquote()
                            << QString("  apertura: %1")
                            .arg(apertura.toString(Qt::ISODate));
                    
                            qDebug().noquote()
                            << QString("  chiusura: %1")
                            .arg(chiusura.toString(Qt::ISODate));
                    
                            qDebug() << "";
                        }
                    

                    It could be that Qt6 is attempting to use mysql binary protocol for prepared statement data transfer, mariadb: Server version: 12.3.2-MariaDB Arch Linux
                    Qt: Using Qt version 6.11.1 in /usr/lib
                    Same code used to work with qt5

                    SGaistS D 2 Replies Last reply
                    0
                    • T Tiziano Bacocco

                      I'm encountering same problem, below is a simpler test case

                      +----------+----------+------+-----+---------+----------------+
                      | Field    | Type     | Null | Key | Default | Extra          |
                      +----------+----------+------+-----+---------+----------------+
                      | id       | int(11)  | NO   | PRI | NULL    | auto_increment |
                      | apertura | datetime | NO   |     | NULL    |                |
                      | chiusura | datetime | NO   |     | NULL    |                |
                      +----------+----------+------+-----+---------+----------------+
                      

                      This works

                      QSqlQuery query(db);
                      
                          if (!query.exec("SELECT * FROM giornate WHERE id = 56")) {
                              qCritical() << "Query failed:";
                              qCritical() << query.lastError().text();
                              return 1;
                          }
                      
                          while (query.next()) {
                              int id = query.value("id").toInt();
                      
                              // Qt automatically converts SQL DATETIME to QDateTime
                              QDateTime apertura = query.record().value("apertura").value<QDateTime>();
                              QDateTime chiusura = query.value("chiusura").toDateTime();
                      
                              qDebug().noquote()
                              << QString("ID: %1").arg(id);
                      
                              qDebug().noquote()
                              << QString("  apertura: %1")
                              .arg(apertura.toString(Qt::ISODate));
                      
                              qDebug().noquote()
                              << QString("  chiusura: %1")
                              .arg(chiusura.toString(Qt::ISODate));
                      
                              qDebug() << "";
                          }
                      

                      This doesn't

                      QSqlQuery query(db);
                          query.prepare("SELECT * FROM giornate WHERE id = ?");
                          query.bindValue(0,56);
                          if (!query.exec()) {
                              qCritical() << "Query failed:";
                              qCritical() << query.lastError().text();
                              return 1;
                          }
                      
                          while (query.next()) {
                              int id = query.value("id").toInt();
                      
                              // Qt automatically converts SQL DATETIME to QDateTime
                              QDateTime apertura = query.record().value("apertura").value<QDateTime>();
                              QDateTime chiusura = query.value("chiusura").toDateTime();
                      
                              qDebug().noquote()
                              << QString("ID: %1").arg(id);
                      
                              qDebug().noquote()
                              << QString("  apertura: %1")
                              .arg(apertura.toString(Qt::ISODate));
                      
                              qDebug().noquote()
                              << QString("  chiusura: %1")
                              .arg(chiusura.toString(Qt::ISODate));
                      
                              qDebug() << "";
                          }
                      

                      It could be that Qt6 is attempting to use mysql binary protocol for prepared statement data transfer, mariadb: Server version: 12.3.2-MariaDB Arch Linux
                      Qt: Using Qt version 6.11.1 in /usr/lib
                      Same code used to work with qt5

                      SGaistS Offline
                      SGaistS Offline
                      SGaist
                      Lifetime Qt Champion
                      wrote last edited by
                      #22

                      @Tiziano-Bacocco hi,

                      Which error message are you getting ?

                      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
                      • T Offline
                        T Offline
                        Tiziano Bacocco
                        wrote last edited by
                        #23

                        Hi, probably the above issue is related to this
                        https://jira.mariadb.org/projects/CONC/issues/CONC-821?filter=allopenissues

                        getting no error, just invalid qdatetime object, isnull returns false, but qdatetime is invalid

                        Christian EhrlicherC 1 Reply Last reply
                        1
                        • T Tiziano Bacocco

                          Hi, probably the above issue is related to this
                          https://jira.mariadb.org/projects/CONC/issues/CONC-821?filter=allopenissues

                          getting no error, just invalid qdatetime object, isnull returns false, but qdatetime is invalid

                          Christian EhrlicherC Offline
                          Christian EhrlicherC Offline
                          Christian Ehrlicher
                          Lifetime Qt Champion
                          wrote last edited by
                          #24

                          @Tiziano-Bacocco said in QSqlQuery in Qt6: in-place vs prepared:

                          Hi, probably the above issue is related to this

                          Yes, it is. Thanks for the pointer

                          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
                          0
                          • T Tiziano Bacocco

                            I'm encountering same problem, below is a simpler test case

                            +----------+----------+------+-----+---------+----------------+
                            | Field    | Type     | Null | Key | Default | Extra          |
                            +----------+----------+------+-----+---------+----------------+
                            | id       | int(11)  | NO   | PRI | NULL    | auto_increment |
                            | apertura | datetime | NO   |     | NULL    |                |
                            | chiusura | datetime | NO   |     | NULL    |                |
                            +----------+----------+------+-----+---------+----------------+
                            

                            This works

                            QSqlQuery query(db);
                            
                                if (!query.exec("SELECT * FROM giornate WHERE id = 56")) {
                                    qCritical() << "Query failed:";
                                    qCritical() << query.lastError().text();
                                    return 1;
                                }
                            
                                while (query.next()) {
                                    int id = query.value("id").toInt();
                            
                                    // Qt automatically converts SQL DATETIME to QDateTime
                                    QDateTime apertura = query.record().value("apertura").value<QDateTime>();
                                    QDateTime chiusura = query.value("chiusura").toDateTime();
                            
                                    qDebug().noquote()
                                    << QString("ID: %1").arg(id);
                            
                                    qDebug().noquote()
                                    << QString("  apertura: %1")
                                    .arg(apertura.toString(Qt::ISODate));
                            
                                    qDebug().noquote()
                                    << QString("  chiusura: %1")
                                    .arg(chiusura.toString(Qt::ISODate));
                            
                                    qDebug() << "";
                                }
                            

                            This doesn't

                            QSqlQuery query(db);
                                query.prepare("SELECT * FROM giornate WHERE id = ?");
                                query.bindValue(0,56);
                                if (!query.exec()) {
                                    qCritical() << "Query failed:";
                                    qCritical() << query.lastError().text();
                                    return 1;
                                }
                            
                                while (query.next()) {
                                    int id = query.value("id").toInt();
                            
                                    // Qt automatically converts SQL DATETIME to QDateTime
                                    QDateTime apertura = query.record().value("apertura").value<QDateTime>();
                                    QDateTime chiusura = query.value("chiusura").toDateTime();
                            
                                    qDebug().noquote()
                                    << QString("ID: %1").arg(id);
                            
                                    qDebug().noquote()
                                    << QString("  apertura: %1")
                                    .arg(apertura.toString(Qt::ISODate));
                            
                                    qDebug().noquote()
                                    << QString("  chiusura: %1")
                                    .arg(chiusura.toString(Qt::ISODate));
                            
                                    qDebug() << "";
                                }
                            

                            It could be that Qt6 is attempting to use mysql binary protocol for prepared statement data transfer, mariadb: Server version: 12.3.2-MariaDB Arch Linux
                            Qt: Using Qt version 6.11.1 in /usr/lib
                            Same code used to work with qt5

                            D Offline
                            D Offline
                            dviktor
                            wrote last edited by
                            #25

                            @Tiziano-Bacocco thank you a lot for finding this! I'll check which MariaDB version I have on my production server (with the same behavior). So it looks like to be a bug in MariaDB / Connector interface rather than Qt side.
                            Thanks to all who took care and participation in tries to dig that out!

                            T 1 Reply Last reply
                            0
                            • D dviktor

                              @Tiziano-Bacocco thank you a lot for finding this! I'll check which MariaDB version I have on my production server (with the same behavior). So it looks like to be a bug in MariaDB / Connector interface rather than Qt side.
                              Thanks to all who took care and participation in tries to dig that out!

                              T Offline
                              T Offline
                              Tiziano Bacocco
                              wrote last edited by
                              #26

                              @dviktor With the version shipped with debian trixie 11.8.6-MariaDB-0+deb13u1 , it works properly

                              1 Reply Last reply
                              0

                              • Login

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