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. QSqlQueryModel & QSqlQuery::prepare - app crash
Forum Updated to NodeBB v4.3 + New Features

QSqlQueryModel & QSqlQuery::prepare - app crash

Scheduled Pinned Locked Moved General and Desktop
12 Posts 3 Posters 5.0k 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.
  • M Offline
    M Offline
    michmu
    wrote on last edited by
    #3

    I found out, that the error is triggered when I have this line:
    @QSqlDatabase::removeDatabase(QSqlDatabase::database().connectionName());@

    in my MainWindow::~MainWindow (destructor). Executing this line writes this:

    bq. QSqlDatabasePrivate::removeDatabase: connection 'qt_sql_default_connection' is still in use, all queries will cease to work.

    And next - the error is triggered. I heve just posted the code example to the bugreport (QTBUG-43889) .

    Is it sufficient to just call
    @QSqlDatabase::database().close();@

    to properly free the connection? Maybe I don't need to call QSqlDatabase::removeDatabase ?

    1 Reply Last reply
    0
    • C Offline
      C Offline
      clochydd
      wrote on last edited by
      #4

      Hi,
      try this in the destructor:
      @
      yourDatabase = QSqlDatabase();
      QSqlDatabase::removeDatabase(yourDatabase.connectionName());
      @

      1 Reply Last reply
      0
      • M Offline
        M Offline
        michmu
        wrote on last edited by
        #5

        [quote author="Clochydd" date="1422090466"]Hi,
        try this in the destructor:
        @
        yourDatabase = QSqlDatabase();
        QSqlDatabase::removeDatabase(yourDatabase.connectionName());
        @
        [/quote]

        Tried it - no effect:
        @dbTestGUI::~dbTestGUI()
        {
        QSqlDatabase db = QSqlDatabase::database();
        //db.close();
        QSqlDatabase::removeDatabase(db.connectionName()); //this line causes error
        }@

        1 Reply Last reply
        0
        • C Offline
          C Offline
          clochydd
          wrote on last edited by
          #6

          Hi,
          I always open my databases that way:
          @
          db = QSqlDatabase::addDatabase("QPSQL");
          db.setDatabaseName("myDB");
          db.setHostName("localhost");
          db.setPort(5432);
          if (!db.open("user", "password")) {
          ...
          }
          ...
          @

          and close it the destructor:

          @
          db = QSqlDatabase();
          QSqlDatabase::removeDatabase(db.connectionName());
          @

          1 Reply Last reply
          0
          • M Offline
            M Offline
            michmu
            wrote on last edited by
            #7

            According to the doc:

            bq. QSqlDatabase::​QSqlDatabase()
            Creates an empty, invalid QSqlDatabase object. Use addDatabase(), removeDatabase(), and database() to get valid QSqlDatabase objects.

            So I guess that you remove an invalid database - which probably doesn't do anything at all...

            1 Reply Last reply
            0
            • M Offline
              M Offline
              michmu
              wrote on last edited by
              #8

              As i thought - when using your code - nothing happens. Neither is the connection closed (I can still see it it PgAdmin's "server status window":http://www.pgadmin.org/docs/dev/status.html), nor are the dll's unloaded. So I guess - that you'have been always closing it the wrong way :)

              1 Reply Last reply
              0
              • C Offline
                C Offline
                clochydd
                wrote on last edited by
                #9

                Just checked with pgAdmin's server status:
                The connection appears when any of my postgres based programs is opened and disappears when the program is closed...

                I came to the above described solution after several weeks of trial and error and with support by this forum.

                1 Reply Last reply
                0
                • M Offline
                  M Offline
                  michmu
                  wrote on last edited by
                  #10

                  Well, yes. The connection is created when you call QSqlDatabase::open. And it is closed as the application is closed - even if you don't call anything in the destructor. What I meant, is that if you execute and debug your code line-by-line - it does nothing.
                  Consider the following:
                  @dbTestGUI::~dbTestGUI()
                  {
                  QSqlDatabase db = QSqlDatabase();
                  qDebug() << db.isValid(); //returns false
                  db.close(); //does nothing - connection still visible in pgadmin server status
                  QSqlDatabase::removeDatabase(db.connectionName()); does nothig - no effect visible
                  }@

                  versus:
                  @dbTestGUI::~dbTestGUI()
                  {
                  QSqlDatabase db = QSqlDatabase().database();
                  qDebug() << db.isValid(); //returns true
                  db.close(); //connection disappears from server status
                  QSqlDatabase::removeDatabase(db.connectionName()); // sometimes some DLL's get unloaded, sometimest not.
                  //the following line appears on the console: "QSqlDatabasePrivate::removeDatabase: connection ‘qt_sql_default_connection’ is still in use, all queries will cease to work."
                  }@

                  When run the app, after executing this destructor it crashes. But when i comment the line:
                  @QSqlDatabase::removeDatabase(db.connectionName()); @

                  it doesn't

                  1 Reply Last reply
                  0
                  • M Offline
                    M Offline
                    michmu
                    wrote on last edited by
                    #11

                    So, to sum up - this is my destructor now:
                    @dbTestGUI::~dbTestGUI()
                    {
                    QSqlDatabase db = QSqlDatabase().database();
                    qDebug() << db.isValid();
                    db.close();
                    //QSqlDatabase::removeDatabase(db.connectionName()); //this line results in error after executing the d-tor
                    }@
                    when stepping out of it, I get the following message:

                    bq. Unable to free statement: connection pointer is NULL

                    So i guess, that Qt has a general problem with free'ing Prepared Statemets. Probably, because on one hand the QSqlQuery object is copied to the model (via QSqlQueryModel::setQuery), ant on the other hand ​QSqlQuery's parent is QSqlDatabase:
                    @QSqlQuery::​QSqlQuery(const QString & query = QString(), QSqlDatabase db = QSqlDatabase()) @

                    So instead of deallocating the query when the model is deleted - it is dealocated, when the database object gets destroyed.

                    1 Reply Last reply
                    0
                    • M Offline
                      M Offline
                      michmu
                      wrote on last edited by
                      #12

                      I guess I solved it. When the model is initialized as view's child:
                      @model = new QSqlQueryModel(this);@
                      The problem is order of operations. When I close the connection and remove the database in the destructor of my class - the database gets disconnected and no further operations are possible. But after my class' destructor, destructors of its base classes get into action - one by another, as ordered by inheritance. When Qobject::~Qobject() is executed, it gets to the
                      @QObjectPrivate::deleteChildren() @

                      method. And then, it finally gets to delete the model. The model wants to free the resources - which means QSqlResult (QPSQLResult to be specific in that case). This it how it looks:

                      @QPSQLResult::~QPSQLResult()
                      {
                      Q_D(QPSQLResult);
                      cleanup();

                      if (d->preparedQueriesEnabled && !d->preparedStmtId.isNull())
                          d->deallocatePreparedStmt();
                      

                      }@

                      So here Qt tries to deallocate preparedStatement - regardless of the fact, that the connection no longer exists:
                      @void QPSQLResultPrivate::deallocatePreparedStmt()
                      {
                      const QString stmt = QLatin1String("DEALLOCATE ") + preparedStmtId;
                      PGresult *result = privDriver()->exec(stmt);

                      if (PQresultStatus(result) != PGRES_COMMAND_OK)
                          qWarning("Unable to free statement: %s", PQerrorMessage(privDriver()->connection));
                      PQclear(result);
                      preparedStmtId.clear();
                      

                      }@

                      So - to make it work properly, I wolud have to call
                      @QSqlQueryModel::~QSqlQueryModel() @

                      or
                      @QSqlQueryModel::clear()@

                      BEFORE closing the connection with the DB. I still think it's a bug.

                      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