3

I have a folder where i have a many databases. Some times may be deleted or added database to the folder. So I use QTimer and read all databases.

It is a my code:

this->timer = new QTimer(this);
this->timer->setInterval(15000);
connect(this->timer, &QTimer::timeout, this, [=]() {
    QString path = "C:\\Users\\User\\Desktop\\DAXI SMS SENDER\\SMSSenderAllBASE";
    //QString path = qApp->applicationDirPath() + "\\SMSSenderAllBASE";
    QDir recoredDir(path);
    QStringList allFiles = recoredDir.entryList(QDir::NoDotAndDotDot | QDir::System | QDir::Hidden  | QDir::AllDirs | QDir::Files, QDir::DirsFirst);
    for (int i = 0; i < allFiles.size(); i++) {
        QString fullPath = path + "\\" + allFiles[i];
        QString connectionName = allFiles[i];
        connectionName = connectionName.remove(connectionName.size() - 4, 4);
        QSqlDatabase db = QSqlDatabase::addDatabase("QIBASE", connectionName);
        db.setDatabaseName(fullPath);
        db.setHostName("localhost");
        db.setPort(3050);
        db.setUserName("SYSDBA");
        db.setPassword("masterkey");

        thrdHelperSendSMS *help = new thrdHelperSendSMS(db, this);
        connect(help, &thrdHelperSendSMS::helperFinished, this, [=](QString connectionName){
            QSqlDatabase t_db = QSqlDatabase::database(connectionName);
            t_db.close();
            QSqlDatabase::removeDatabase(connectionName);
            delete help;
        });
        help->run();
    }
});
this->timer->start();

Yes I'm sure that the helperFinished signal will happen and this time I will not have any connection with this base.

EDIT: If i remove

   thrdHelperSendSMS *help = new thrdHelperSendSMS(db, this);
   connect(help, &thrdHelperSendSMS::helperFinished, this, [=](QString connectionName){
       QSqlDatabase t_db = QSqlDatabase::database(connectionName);
       t_db.close();
       QSqlDatabase::removeDatabase(connectionName);
       delete help;
   });
   help->run();

example:

for (int i = 0; i < allFiles.size(); i++) {
    QString fullPath = path + "\\" + allFiles[i];
    QString connectionName = allFiles[i];
    connectionName = connectionName.remove(connectionName.size() - 4, 4);
    QSqlDatabase db = QSqlDatabase::addDatabase("QIBASE", connectionName);
    db.setDatabaseName(fullPath);
    db.setHostName("localhost");
    db.setPort(3050);
    db.setUserName("SYSDBA");
    db.setPassword("masterkey");

    QSqlDatabase::removeDatabase(connectionName);
}

I have the same error.

Tazo leladze
  • 1,430
  • 1
  • 16
  • 27

4 Answers4

13

You don't use removeDatabase() correctly. The object of SqlDatabase needs to go out of scope first. See documentation.

Wrong use

QSqlDatabase db = QSqlDatabase::database("sales");
QSqlQuery query("SELECT NAME, DOB FROM EMPLOYEES", db);
QSqlDatabase::removeDatabase("sales"); // will output a warning

Correct use

{
    QSqlDatabase db = QSqlDatabase::database("sales");
    QSqlQuery query("SELECT NAME, DOB FROM EMPLOYEES", db);
}
// Both "db" and "query" are destroyed because they are out of scope
QSqlDatabase::removeDatabase("sales"); // correct

In the second example db will go out of scope after } and you will no longer see the error message QSqlDatabasePrivate::removeDatabase: connection 'myConnectionName' is still in use, all queries will cease to work

Please read the documentation carefully. The database stuff is sensible and every line needs to be checked carefully.

Also you have missing db.close(); - It makes sense to close the database before you remove it.

user3606329
  • 2,405
  • 1
  • 16
  • 28
4

@user3606329's answer is right, but I add this possibility:

QSqlDatabase db = QSqlDatabase::database("sales");
{
    QSqlQuery query("SELECT NAME, DOB FROM EMPLOYEES", db);
    //use query
}
db = QSqlDatabase();
QSqlDatabase::removeDatabase("sales");
Albertino80
  • 1,063
  • 7
  • 21
  • Nice one, thanks! I had to get a class' on-stack member `QSqlDatabase` to go "out of scope" in its destructor before removing the corresponding database from the global pool, and this method worked perfectly. – Maxim Paperno Jan 02 '23 at 18:38
0

You can use std::swap to force it destruct on demand. I basically use BOOST_SCOPE_EXIT for cases when want to call a function on scope exit including not expected exit like through an exception throw.

#include <boost/scope_exit.hpp>

{
    QSqlDatabase db;

    BOOST_SCOPE_EXIT(this_, &db) { // by reference, otherwise it will copy a stack object
        // access object here through the this_ instead of this ...

        if (db.isOpen()) {
            db.close(); // closing if not yet closed before connection remove
        }

        std::swap(db, QSqlDatabase{}); // destruct via swap

        // CAUTION:
        //  From this point you must not call to `QSqlDatabase::database("MYDB", ...)`, otherwise it will return another constructed object!
        //

        QSqlDatabase::removeDatabase("MYDB");
    } BOOST_SCOPE_EXIT_END

    // ui change from here ...

    // accomplish last ui changes before long blocking operation
    qApp->processEvents();

    db = QSqlDatabase::addDatabase("...", "MYDB");

    // database access from here ...
}
Andry
  • 2,273
  • 29
  • 28
-1
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", "conn_name");
db.open();
if (db.open())
    {
        qDebug()<<"DataBase is Open";
    }
    else
    {
        qDebug()<<"DataBase is Not Open";

    }
QSqlQueryModel * model = new QSqlQueryModel();
QSqlQuery query(QSqlDatabase::database("conn_name"));
query.exec("SMTHING")
if (query.exec())
{
   while (query.next())
      {
         ui->QTableView->setModel(model);
         model->setHeaderData(2, Qt::Horizontal, QObject::tr("????"));
      }
}
db.close();
QSqlDatabase::removeDatabase("conn_name");



Here is my code
GKS
  • 19
  • 4