0

I found other similar questions with the same error (i.e. this and this) but apparently all of them are related to a wrong library / configuration since the users cannot connect to the database at all.

In my case instead I can successfully connect to the remote SQLServer database. The error comes up only when the remote host goes down and then comes back online. In this case I receive:

[unixODBC][Driver Manager]Driver's SQLAllocHandle on SQL_HANDLE_HENV failed"

until I restart my application. Here the code I use to connect to the database:

bool OdbcSql::connectToDB(QUrl host, QString database, QString username, QString password)
{
    _host = host;
    _database = database;
    _username = username;
    _password = password;

    if (_db.isOpen()) _db.close();
    _db.removeDatabase("production");
    _db = QSqlDatabase::addDatabase("QODBC", "production");

    qInfo() << ID << "Trying to open database...";
    _db.setDatabaseName(QStringLiteral("Driver=/opt/microsoft/msodbcsql18/lib64/libmsodbcsql-18.2.so.1.1; Server=%1;Database=%2; Encrypt=No;").arg(host.url()).arg(database));
    _db.setUserName(username);
    _db.setPassword(password);
    _db.setConnectOptions("SQL_ATTR_CONNECTION_TIMEOUT=5;SQL_ATTR_LOGIN_TIMEOUT=5;SQL_ATTR_CONNECTION_POOLING=SQL_CP_OFF;");

    bool ret = _db.open();
    if (ret) qInfo() << ID << "Database opened successfully";
    else qWarning() << ID << "Database opening failed:" << _db.lastError();

    return ret;
}

I'm using Ubuntu 22.04, Qt 6.4.0, libmsodbcsql-18.2 as odbc driver.

UPDATE

Here the complete sequence to replicate the behavior.

  1. start my application
  2. let's say the remote host is not available (offline)
  3. the connect fails due to login timeout
  4. every minute it tries again, calling the function above
  5. the remote host is online
  6. the connect works and I can use the database
  7. after some time the remote host goes offline
  8. I detect the loss of connection (see below)
  9. every minute it tries again, calling the function above but it fails due to timeout login
  10. the remote host comes back online
  11. I get the SQL_HANDLE_HENV error
  12. the online way to connect again to the database is to stop and run again my application

Here the code I use to detect the loss of connection:

bool OdbcSql::checkConnectivity()
{
    if (!_isConnected) return false;
    if (_db.transaction())
    {
        _db.rollback();
        return true;
    }
    else
    {
        _isConnected = false;
        _db.close();
        qWarning() << ID << "Lost connection to database";
        return false;
    }
}

I cannot use the QSqlDatabase::isOpen() method because it does not return the actual state of the connection. I found this code here on StackOverflow and in the QtForum.

5
  • could you explain a bit more how it works. What's the sequence of events which leads to errors. Is it: 1) you start app 2) you connect and it works 3) host dies 4) you connect again 5) crash? Commented Oct 2, 2023 at 10:46
  • @siggemannen yes, exactly. Anyway, I've updated the question with more details! thanks Commented Oct 2, 2023 at 12:31
  • Please follow the documentation and do not hold a local QSqlDatabase instance. In your code removeDatbase() will not work as expected which might also cuase your problem. Commented Oct 2, 2023 at 15:28
  • @chehrlic not sure to understand that snippet. It means I have to declare QSqlDatabase db = QSqlDatabase::database("sales"); in every function so it gets destroyed when it exits the function? Commented Oct 2, 2023 at 16:00
  • Yes - this is what the documentation tells you: doc.qt.io/qt-6/qsqldatabase.html#details Commented Oct 2, 2023 at 19:35

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.