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. QSqlDriver - misunderstandings?
Forum Updated to NodeBB v4.3 + New Features

QSqlDriver - misunderstandings?

Scheduled Pinned Locked Moved Unsolved General and Desktop
7 Posts 2 Posters 348 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.
  • D Offline
    D Offline
    django.Reinhard
    wrote on last edited by
    #1

    Hi,

    I have a strange behaviour. I compiled the Sqldriver for MariaDB and wrote a testapp, which works fine.

    In my real app, I'm doing this:

    In init() from MainWindow (called by singleshot timer 0):

      db.setHostName(dbc.dbHost());
      if (!db.open(dbc.dbUser(), dbc.dbPass()))
         throw new std::domain_error("can NOT connect to database");
      if (!db.isDriverAvailable(dbc.driver()))
         throw new std::domain_error("db-driver not available!");
      if (db.driver()->isOpenError())
         throw new std::domain_error("db-driver has OPEN error!");
      if (!db.driver()->isOpen())
         throw new std::domain_error("db-driver not opened!");
      Service::ValueManager().setValue("dbName", dbc.dbName());
    

    later during same init I use a loaded plugin to check and possibly setup the database.
    First the check:

      QSqlDatabase db = QSqlDatabase::database(Service::ValueManager().getValue("dbName").toString());
      QSqlQuery    sql(db);
      int          count = 0;
    
      try {
          bool rv = sql.exec("Select count(*) from SysEvents");
    
          while (sql.next())
                count = sql.value(0).toInt();
          }
      catch (std::exception* e) {
          qDebug() << "failed to check database:" << e->what();
          db.driver()->rollbackTransaction();
          }
      catch (std::exception& e) {
          qDebug() << "failed to check database:" << e.what();
          db.driver()->rollbackTransaction();
          }
      return count > 0;
    

    No error, no exception. dbName is set and init function continues ...
    Initially there's no table in the database, so count is 0.
    I stepped through the code - no exception ...

    ValueManager manages ownerless properties used as global vars.

    If above count is 0, table creation is initiated:

      QSqlDatabase db = QSqlDatabase::database(Service::ValueManager().getValue("dbName").toString());
    
      if (!db.isOpen())
         throw new std::domain_error("database has NOT been opened!");
      if (!db.driver()->isOpenError())
         throw new std::domain_error("db-driver has OPEN error");
      if (!db.driver()->isOpen())
         throw new std::domain_error("db-driver not opened!");
    
      if (!createTable(db))
         throw new std::domain_error(QString("failed to create Table: %1")
                                        .arg(QSqlDatabase::database().driver()->lastError().text()).toStdString());
    

    This time, here in createTable function, db.driver()->isOpenError() is true, so an exception is thrown.

    Obviously database-driver worked at begin of init-function, but error (may be wrong error message?) is active after selecting a non-existing table.

    How can I reset such an error condition?

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

      Check if Service::ValueManager().getValue("dbName").toString() really returns the same value everywhere, also look what db.hostName(), password() and others returns in the various functions.

      btw: neither sql.exec() nor sql.next() throws an exception (but returns a bool which should be checked) so the try/catch block is useless.

      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
      2
      • D Offline
        D Offline
        django.Reinhard
        wrote on last edited by
        #3

        @Christian-Ehrlicher said in QSqlDriver - misunderstandings?:

        Check if Service::ValueManager().getValue("dbName").toString() really returns the same value everywhere, also look what db.hostName(), password() and others returns in the various functions.

        I couldn't believe it, as I already have unittest to ensure proper work with multiple threads and this time its all in one thread.

        any way ... I added some debug statements ...

        check for existing data changed to:

          QString      dbName = Service::ValueManager().getValue("dbName").toString();
          QSqlDatabase db = QSqlDatabase::database(dbName);
          QSqlQuery    sql(db);
          int          count = 0;
        
          qDebug() << "check:   vm - dbName =" << dbName;
          qDebug() << "check: database name =" << db.databaseName();
          if (!db.isOpen())
        

        ... and this is the log output:

        VM: new model created for > "dbName" < - value: [ QVariant(QString, "myDB") ]
        check:   vm - dbName = "myDB"
        check: database name = ""
        
        1 Reply Last reply
        0
        • D Offline
          D Offline
          django.Reinhard
          wrote on last edited by
          #4

          Just to verify that network access to mariadb works, I changed connection.h from relationaltablemodel example to use network access of mariadb.

          Then I adapted my database testproject:

          #include <QCoreApplication>
          #include <QLocale>
          #include <QTranslator>
          #include <QSqlDatabase>
          #include <QSqlQuery>
          #include <QSqlError>
          #include <QDebug>
          
          
          static void tellDrivers() {
            QStringList  dl = QSqlDatabase::drivers();
          
            for (int i=0; i < dl.size(); ++i) {
                qDebug() << "driver:" << dl.at(i) << "is"
                         << (QSqlDatabase::isDriverAvailable(dl.at(i)) ? "available"
                                                                       : "NOT available");
                }
            }
          
          
          static void connect() {
            QSqlDatabase db = QSqlDatabase::addDatabase("QMARIADB", "testDB");
          
            db.setDatabaseName("testDB");
            db.setHostName("netHost");
            if (!db.open("testUser", "testPass")) {
               qDebug() << "failed to access database with:" << db.lastError();
               }
            qDebug() << "opened database" << db.databaseName() << "with driver" << db.driverName();
            }
          
          
          static void checkConnection() {
            QStringList sl = QSqlDatabase::connectionNames();
            bool foundOpenDB = false;
          
            for (int i=0; i < sl.size(); ++i) {
                QSqlDatabase db = QSqlDatabase::database(sl.at(i), false);
          
                if (db.isOpen()) {
                   qDebug() << "found open database:" << db.databaseName();
                   foundOpenDB = true;
                   }
                }
            if (!foundOpenDB) qDebug() << "no opened database found!";
            }
          
          
          static int getData() {
            QSqlDatabase db = QSqlDatabase::database("testDB");
          
            if (!db.isOpen()) {
               qDebug() << "Database is NOT open :(";
               return 0;
               }
            QSqlQuery query(db);
            int count = 0;
          
            query.exec("SELECT * FROM person");
          
            while (query.next()) {
                  int     id    = query.value(0).toInt();
                  QString fname = query.value(1).toString();
                  QString lname = query.value(2).toString();
          
                  qDebug() << "\t" << id << fname << lname;
                  ++count;
                  }
            return count;
            }
          
          
          static void closeConnection() {
            QStringList sl = QSqlDatabase::connectionNames();
          
            for (int i=0; i < sl.size(); ++i) {
                QSqlDatabase db = QSqlDatabase::database(sl.at(i), false);
          
                if (db.isOpen()) {
                   qDebug() << "gonna close database:" << db.databaseName();
                   db.close();
                   }
                }
            }
          
          
          int main(int argc, char *argv[]) {
            QCoreApplication a(argc, argv);
            QTranslator translator;
            const QStringList uiLanguages = QLocale::system().uiLanguages();
          
            for (const QString &locale : uiLanguages) {
                const QString baseName = "DatabaseTest_" + QLocale(locale).name();
                if (translator.load(":/i18n/" + baseName)) {
                   a.installTranslator(&translator);
                   break;
                   }
                }
            tellDrivers();
            qDebug() << "1";
            connect();
            qDebug() << "2";
            checkConnection();
            qDebug() << "3";
            int rv = getData();
          
            qDebug() << "4\tgot" << rv << "records";
            closeConnection();
            qDebug() << "5";
            checkConnection();
            qDebug() << "6";
          
            return 0;
            }
          

          ... and this is the Log-Output:

          driver: "QMARIADB" is available
          driver: "QMYSQL" is available
          driver: "QPSQL" is available
          driver: "QODBC" is available
          driver: "QSQLITE" is available
          1
          opened database "testDB" with driver "QMARIADB"
          2
          found open database: "testDB"
          3
          	 101 "Danny" "Young"
          	 102 "Christine" "Holand"
          	 103 "Lars" "Gordon"
          	 104 "Roberto" "Robitaille"
          	 105 "Maria" "Papadopoulos"
          4	got 5 records
          gonna close database: "testDB"
          5
          no opened database found!
          6
          
          1 Reply Last reply
          0
          • Christian EhrlicherC Offline
            Christian EhrlicherC Offline
            Christian Ehrlicher
            Lifetime Qt Champion
            wrote on last edited by
            #5

            So since your second app works you're doing something wrong in the other one. As I said you should print out some debug stuff everywhere you access Service::ValueManager().getValue("dbName").toString(); and getting the QSqlDatabase object afterwards to see if it's the same / if it is still open but you didn't until now.

            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
              django.Reinhard
              wrote on last edited by
              #6

              Hi Christian,

              @Christian-Ehrlicher said in QSqlDriver - misunderstandings?:

              As I said you should print out some debug stuff everywhere you access Service::ValueManager().getValue("dbName").toString();

              when you look at my post, I added some debug statements and posted the debug output:

              @django-Reinhard said in QSqlDriver - misunderstandings?:

              check for existing data changed to:
              QString dbName = Service::ValueManager().getValue("dbName").toString();
              QSqlDatabase db = QSqlDatabase::database(dbName);
              QSqlQuery sql(db);
              int count = 0;

              qDebug() << "check: vm - dbName =" << dbName;
              qDebug() << "check: database name =" << db.databaseName();
              if (!db.isOpen())

              ... and this is the log output:
              VM: new model created for > "dbName" < - value: [ QVariant(QString, "myDB") ]
              check: vm - dbName = "myDB"
              check: database name = ""

              So you can see, that the name from ValueManager is correct, but QSqlDatabase returns an empty name.

              The only difference between working sample and failing app (as far as I know) is, that the working sample is one source file, whereas the failing app is an app + a dynamically loaded plugin.

              It makes no difference, whether the code for connecting with user+password is from main-app or plugin. Connecting with user+password works, but reusing an open connection does not work.
              Plugin-code is called from Main-thread and Mainwindow-init().

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

                Please post a minimal, compilable example - I really don't know anymore where you added what and why. You posted a working solution so it must be a problem sonwehere in your code.

                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

                • Login

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