Sorry if this is a trivial question but I have been trying to build a small .ui that used QSQLITE
as database and that uses QTableView
to show 4 columns on a default database file as example.
I debugged the problem in every side, changed logical operations of the SQL
and restructured the constructor in a more simple way but the error still stays.
After finishing to set up all parameters I am getting this error:
QSqlDatabasePrivate::removeDatabase: connection 'qt_sql_default_connection' is still in use, all queries will cease to work.
And
QSqlDatabasePrivate::addDatabase: duplicate connection name 'qt_sql_default_connection', old connection removed.
I looked on several sources that describe this error such as this source, this other source. Also this was useful but still nothing happens. Official documentation suggests a "wrong" and "right" way to do that here. but the error still stays. After all these different options I brought back the code to a more concise way and I hope that someone can shed light on this issue.
Below the snipped of code:
mainwindow.h
private:
QString temporaryFolder;
dataInfo *mNewDatabaseImages;
QSqlTableModel *mNewTableImages;
mainwindow.cpp
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
temporaryFolder = "/home/to/Desktop/tempDBFolder/tmp.db";
QFile dbRem(temporaryFolder);
dbRem.remove();
mNewDatabaseImages = new dataInfo(this);
mNewDatabaseImages->initDataBase(temporaryFolder);
mNewDatabaseImages->confDataBase();
mNewTableImages = new QSqlTableModel(this, mNewDatabaseImages->getDatabase());
mNewTableImages->setTable("leftCamTable");
mNewTableImages->select();
ui->bookMarkTableView->setModel(mNewTableImages);
ui->bookMarkTableView->showColumn(true);
}
datainfo.h
#ifndef DATAINFO_H
#define DATAINFO_H
#include <QObject>
#include <QSqlDatabase>
#include "imageparam.h"
class dataInfo : public QObject
{
Q_OBJECT
public:
explicit dataInfo(QObject *parent = nullptr);
bool initDataBase(const QString &nameDB);
bool confDataBase();
bool addItem(ImageParam* imageItem);
QSqlDatabase getDatabase();
private:
QString mError;
QSqlDatabase mDBImages;
};
#endif // DATAINFO_H
datainfo.cpp
#include "datainfo.h"
#include <QSqlQuery>
#include <QSqlError>
#include <QDebug>
#include <QVariant>
#include <QMessageBox>
#define CREATE_TABLE \
" CREATE TABLE IF NOT EXISTS imageTable" \
" (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL" \
" path1 TEXT NOT NULL" \
" path2 TEXT NOT NULL" \
" imageA BLOB NOT NULL" \
" imageB BLOB NOT NULL)"
dataInfo::dataInfo(QObject *parent) : QObject(parent)
{}
bool dataInfo::initDataBase(const QString &nameDB)
{
mDBImages = QSqlDatabase::addDatabase("QSQLITE");
mDBImages.setDatabaseName(nameDB);
bool ok = mDBImages.open();
if(!ok) {
mError = mDBImages.lastError().text();
qDebug() << mError;
}
return ok;
}
bool dataInfo::confDataBase()
{
QSqlQuery qry;
bool ok = qry.exec(CREATE_TABLE);
if(!ok) {
mError = qry.lastError().text();
}
return ok;
}
bool dataInfo::addItem(ImageParam *imageItem)
{
QSqlQuery qry;
qry.prepare("INSERT INTO imageTable (path1, path2, imageA, imageB)" \
" VALUES (?,?,?,?)");
qry.addBindValue(imageItem->path1());
qry.addBindValue(imageItem->path2());
qry.addBindValue(imageItem->image1());
qry.addBindValue(imageItem->image2());
bool ok = qry.exec();
if(!ok) {
mError = qry.lastError().text();
}
return ok;
}
QSqlDatabase dataInfo::getDatabase()
{
return mDBImages;
}
I looked also at this post that suggested to set a name to the databse first but I already do that in the function initDataBase(const QString &nameDB)
. Here the post that suggested the procedure, which is below:
db->setDatabaseName("name");
if(!db->open()) {
qDebug() << "Error opening ";
return false;
}
Please shed light on the possible solution.
Short answer
You should specify the database you want to run your
QSqlQuery
on, otherwise they will run on the default database. You can specify the database inQSqlQuery
's constructor withQSqlQuery query(QSqlDatabase::database("my-db"));
You are keeping a copy of the
QSqlDatabase
as a member of yourdataInfo
class, which will prevent it prevent closing properly. Instead, just use the staticQSqlDatabase::database("name")
when needed.auto db = QSqlDatabase::database("my-db");
Details
Providing the right database to QSqlQuery
Change all your uses of
QSqlQuery
. For example forconfDataBase
:Not keeping QSqlDatabase attributes
From the documentation:
Store your database's name in your class instead, and change your
getDatabase
todataInfo.cpp
dataInfo.h
Qt's code generating the warning
To have a look at the actual code producing the error: https://code.woboq.org/qt5/qtbase/src/sql/kernel/qsqldatabase.cpp.html#170
invalidateDb
is used when connections are added or removed, and will trigger the error if the reference count > 1. As you are holding onto one, this will trigger the error.