Getting SQL_HANDLE_HENV failed error only after a disconnection

53 Views Asked by At

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.

0

There are 0 best solutions below