Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

So, I'm having an issue regarding QT and SQL commands, I've been sitting with it for hours, but more likely than not its going to be simple.

I am attempting to have multiple forms, in each one I connect the database, and perform some operations. This works fine, however- as soon as I move said operations to say a button_pressed function, I receive database not open error. I do not close the database anywhere in this class, but the error persists.

I have now seen that part of the problem is the following errors:

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

QSqlDatabasePrivate::addDatabase: duplicate connection name 'qt_sql_default_connection', old connection removed.

When I restructure the code(for debugging) and remove the connection in the first form, then the error goes away, and the database stays open in the second class functions. Below, the secondary class

HomeScreen::HomeScreen(QWidget *parent):QWidget(parent),ui(newUi::HomeScreen){
    ui->setupUi(this);
    connect(ui->btnInclogShow,SIGNAL(pressed()),this,SLOT(ShowLogs()));
    dbe = QSqlDatabase::addDatabase("QMYSQL");
    dbe.setDatabaseName("securitydb");
    dbe.setUserName("root");
    dbe.setPassword("");
    dbe.open();
    if(dbe.open()){
        qDebug() << "Database is open in main part";
    else{qDebug() << "Database is closed";}
HomeScreen::~HomeScreen()
    delete ui;
void HomeScreen::ShowLogs()
    qDebug() << "Showlogs pressed";
    if(dbe.open()){
        qDebug() << "Database is open";
    else{qDebug() << "Database is closed";}

Below the primary class

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
    ui->setupUi(this);
    db = QSqlDatabase::addDatabase("QMYSQL");
    db.setDatabaseName("securitydb");
    db.setUserName("root");
    db.setPassword("");
    db.open();
    connect(ui->btnLogin,SIGNAL(pressed()),this,SLOT(LoginClicked()));
    if(db.open()){
        qDebug() << "Database is open";
    else{qDebug() << "Database is closed";}
MainWindow::~MainWindow()
    delete ui;
    db.close();
    db.removeDatabase("securitydb");
void MainWindow::LoginClicked()
    qDebug() << "pressed";
    this->destroy();
    HomeScreengui->show();

As an attempt to mitigate the issue, I declared a new database variable in the second class, this did not work. Any help would be appreciated!

You say you are not closing the database but you are doing it in the destructor. It is not necessary to open the database in each part of your code, just do it in the main.cpp, QSqlDatabase has a global instance. What do you call destroy? – eyllanesc Oct 28, 2017 at 20:34 Despite the destructor, I still receive the error, thank you for your comment though, I will try opening in main only! – Renierler Oct 29, 2017 at 7:28

First, you have to understand how QSqlDatabase works.

Qt manages a list of database connections. Each connection is identified by a unique name. You can add a new connection, retrieve an existing connection or delete a connection from the list. This is done using the functions:

  • QSqlDatabase::addDatabase()
  • QSqlDatabase::database()
  • QSqlDatabase::removeDatabase()
  • Also several instances of QSqlDatabase can refer to the same connection. So in the following code db0and db1 refer to the same connection.

    QSqlDatabase db0 = QSqlDatabase::addDatabase("MYSQL", "foo");
    QSqlDatabase db1 = QSqlDatabase::database("foo");
    

    Also, in functions that requires a connection name, you can omit the name. Qt will handle it as a default database. This can be handy if you have only one connection.

    Note that Qt uses "qt_sql_default_connection" as the name of the default database. So for instance QSqlDatabase::database() and QSqlDatabase::database("qt_sql_default_connection") return the same connection.

    Now looking at your code. You make calls to QSqlDatabase::addDatabase("QMYSQL"); in both constructors. The second call will add a new connection in the list of connections managed by Qt, and will remove your previous connection. That is why you have the following warning:

    QSqlDatabasePrivate::addDatabase: duplicate connection name 'qt_sql_default_connection', old connection removed.

    Also since the removed connection was in use, you get an extra warning:

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

    To solve this you need to call QSqlDatabase::addDatabase() only once. This can be done by making one of you classes responsible for handling the database connection, the other classes will only call QSqlDatabase::database(), but you must make sureyou have only one instance of this class. Or you can make calls to QSqlDatabase::addDatabase() in every class, but only if the database does not already exist (see QSqlDatabase::contains()):

    // Add a default databse only if it does not exist.
    if (!QSqlDatabase::contains())
        QSqlDatabase::addDatabase("MYSQL");
    

    Also your line db.removeDatabase("securitydb"); is completely wrong. QSqlDatabase::removeDatabase() is a static function and the parameter is a connection name, not a database name. It should be:

    QSqlDatabase::removeDatabase(); // Remove the default database
    

    So your code should look like this:

    HomeScreen::HomeScreen(QWidget *parent):QWidget(parent),ui(newUi::HomeScreen)
        ui->setupUi(this);
        connect(ui->btnInclogShow, &QPushButton::pressed, this, &HomeScreen::ShowLogs);
        if (QSqlDatabase::contains())
            dbe = QSqlDatabase::addDatabase("QMYSQL");
            dbe = QSqlDatabase::database();
        dbe.setDatabaseName("securitydb");
        dbe.setUserName("root");
        dbe.setPassword("");
        if(dbe.open()){
            qDebug() << "Database is open in main part";
        else{
            qDebug() << dbe.lastError().text();
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
        ui->setupUi(this);
        if (QSqlDatabase::contains())
            db = QSqlDatabase::addDatabase("QMYSQL");
            db = QSqlDatabase::database();
        db.setDatabaseName("securitydb");
        db.setUserName("root");
        db.setPassword("");
        connect(ui->btnLogin, &QPushButton::pressed,this, &MainWindow::LoginClicked);
        if(db.open()){
            qDebug() << "Database is open";
        else{
            qDebug() << dbe.lastError().text();
    MainWindow::~MainWindow()
        delete ui;
        // WARNING: If HomeScreen is still using the connection the next 2 lines will leak resources and make HomeScreen lose its connection.
        db.close();
        QSqlDatabase::removeDatabase();
    

    Every time you call addDatabase on the same underlying database, make sure you set a unique connection name:

    if (QSqlDatabase::contains("foo")) {
        QSqlDatabase::removeDatabase("foo");
    db = QSqlDatabase::addDatabase("QMYSQL", "foo");
    db.setDatabaseName("securitydb");
    

    Note that the connection name is not the same as the database name. So here you are opening multiple independent connections to the same database.

    If you don't explicitly set a connection name, Qt will use a default. This default connection name will be used for all accesses to the underlying database. So if you call close() on a database opened with the default connection name, it will effectively close all database objects opened using that default name.

    Thanks for contributing an answer to Stack Overflow!

    • Please be sure to answer the question. Provide details and share your research!

    But avoid

    • Asking for help, clarification, or responding to other answers.
    • Making statements based on opinion; back them up with references or personal experience.

    To learn more, see our tips on writing great answers.