Solved Returning QSqlQueryModel for TableView
-
I want to pass select statement output to tableview. I saw i can do it with QSqlQueryModel. But it does not work.
db.hpublic: QSqlQueryModel* selectData(); QSqlQueryModel *model = new QSqlQueryModel;
db.cpp
QSqlQueryModel* DB::selectData() { model->setQuery("SELECT * FROM mytable"); return *model; }
I am trying to use it in another class's contructor
mypage.cppDB *db = new DB; //Its in mypage.h header actually. ui->tableView->setModel(db->selectData()); //Its in mypage.cpp constructor
Nothing happens. table view comes as empty. I tried putting this code line to button click but still same. Whats wrong in my code? And I want to use db object in several classes. In several classes i will need methods of db class. What is the good way to use same object across multiple classes?
-
return query not queryMode
db.cpp:QSqlQuery DB::selectData() { QSqlQuery model; if(!model.exec("SELECT * FROM mytable")) { qDebug()<<model.lastError(); } return model; }
mypage.cpp:
DB *db = new DB; QSqlQueryModel *model=new QSqlQueryModel; model->setQuery(db->SelectData()); ui->tableView->setModel(model);
-
return query not queryMode
db.cpp:QSqlQuery DB::selectData() { QSqlQuery model; if(!model.exec("SELECT * FROM mytable")) { qDebug()<<model.lastError(); } return model; }
mypage.cpp:
DB *db = new DB; QSqlQueryModel *model=new QSqlQueryModel; model->setQuery(db->SelectData()); ui->tableView->setModel(model);
-
@Emre-MUTLU Thanks it works in this way. Any idea for second question?
-
@masa4 said in Returning QSqlQueryModel for TableView:
What is the good way to use same object across multiple classes?
is this your second question?
-
@Emre-MUTLU
if this your second question you can redefine object in other classes but you need to close and remove old db connection -
@masa4 said in Returning QSqlQueryModel for TableView:
And I want to use db object in several classes
Don't do that!
It is clearly stated in red in the documentation why you should not do that (https://doc.qt.io/qt-6/qsqldatabase.html):
"Warning: It is highly recommended that you do not keep a copy of the QSqlDatabase around as a member of a class, as this will prevent the instance from being correctly cleaned up on shutdown. If you need to access an existing QSqlDatabase, it should be accessed with database(). If you chose to have a QSqlDatabase member variable, this needs to be deleted before the QCoreApplication instance is deleted, otherwise it may lead to undefined behavior." -
DB *db = new DB; QSqlQueryModel *model=new QSqlQueryModel; model->setQuery(db->SelectData()); ui->tableView->setModel(model); delete db;//closed and deleted db objects
db.cpp:
DB::~DB()//db destructor { database.close(); QSqlDatabase::removeDatabase("qt_sql_default_connection");//your dbname here }
example class.cpp:
{ DB *db=new DB; do something delete db; }
example class1.cpp:
DB *db=new DB; do something delete db;//we deleting db object and its call DB destructor
-
@Emre-MUTLU
constructor:DB::DB(const QString &path) { m_db = QSqlDatabase::addDatabase("QSQLITE"); m_db.setDatabaseName(path); if(!m_db.open()) qDebug() << "Error: connection with database failed"; else qDebug() << "Database: connection ok"; qDebug() << m_db.lastError().text(); }
destructor:
DB::~DB() { m_db.close(); m_db.removeDatabase("mypath"); //value of "path" variable in constructor }
and i got:
Database: connection ok "" QSqlDatabasePrivate::addDatabase: duplicate connection name 'qt_sql_default_connection', old connection removed. Database: connection ok "" "" 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. Database: connection ok "" QSqlDatabasePrivate::addDatabase: duplicate connection name 'qt_sql_default_connection', old connection removed. Database: connection ok "" QSqlDatabasePrivate::addDatabase: duplicate connection name 'qt_sql_default_connection', old connection removed. Database: connection ok "" ""
Every time new db oject instantiated with
DB db = new DB();
i got these errors. Im usingdelete db
like you recommended. -
DB::~DB() { m_db.close(); m_db.removeDatabase("qt_sql_default_connection"); }
-
@masa4 There is really no need to add same database connection again and again. Do it once and use it. That is why I pointed you to the documentation. You can get existing database at any time in any place of your application using https://doc.qt.io/qt-6/qsqldatabase.html#database
To analyse the errors you posted: how many DB instances do you have at the same time? Because each of them will try to add same database...
-
DB::~DB() { m_db.close(); m_db.removeDatabase(mypath); your path is string value already so you dont need to use("); }`
-
@Emre-MUTLU , @masa4
Up to you, but as @jsulm/documentation states you really should not have aQSqlDatabase m_db
member variable in a class. If you need to access theQSqlDatabase
instance use static QSqlDatabase QSqlDatabase::database(). -
DB::~DB() { m_db.close(); m_db=QSqlDatabase(); m_db.removeDatabase(mypath); your path is string value already so you dont need to use("); }
like that?
-
@Emre-MUTLU
No! You have aQSqlDatabase m_db
member variable in yourDB
class. Start by getting rid of that variable and then make your code work! Remember that instead you can re-access the current database instance viaQSqlDatabase::database()
if you need it. You may haveQSqlDatabase db
variables local to methods if you wish, but no class member variable which persists for the lifetime of the class. -
@jsulm @JonB So you guys mean change code to like:
DB::DB(const QString &path) { QSqlDatabase::addDatabase("QSQLITE"); QSqlDatabase.setDatabaseName(path); //this doesnt work, the method is not static. if(!QSqlDatabase::open()) //non static, not work qDebug() << "Error: connection with database failed"; else qDebug() << "Database: connection ok"; qDebug() << QSqlDatabase::lastError().text(); //non static, not work }
I got errors from nonstatic functions in this way. And secondly if i try to call from another class( selectData() is method of DB class.)
otherclass.cpp://db = new DB(); //model->setQuery(db->selectData(ui->lineedit->text())); //normally its in this way model->setQuery(QSqlDatabase::database().selectData(ui->lineedit->text())); //No member named 'selectData' in 'QSqlDatabase'
How should i modify my class actually?
-
@masa4 said in Returning QSqlQueryModel for TableView:
So you guys mean change code to like
No, we only suggested to not to have the m_db member variable in your DB class. I don't know why you changed model->setQuery part.
-
@jsulm Ho okay i see, so I will continue to use
db = new DB(); some code delete DB();
paradigm, right? And what can u say for other non static methods? Without
m_db
how will i use them? In destructor i cant useQSqlDatabase::close()
without member variable too. -
@Emre-MUTLU No no i mean i used same path in both sides.
constructor:m_db.setDatabaseName(DB_PATH);
destructor
m_db.removeDatabase(DB_PATH);
I am passing same value to both but i keep getting this error every time
new DB();
called i think:QSqlDatabasePrivate::addDatabase: duplicate connection name 'qt_sql_default_connection', old connection removed.
-
@masa4 said in Returning QSqlQueryModel for TableView:
And what can u say for other non static methods? Without m_db how will i use them?
Which non static members do you mean? As already explained you can get the database instance you need by simply calling QSqlDatabase::database().
And with your current implementation you're still creating the connection everytime you create a DB instance. You should use https://doc.qt.io/qt-6/qsqldatabase.html#contains to check whether the connection already exist and only add the connection if it does not yet exist.
-
@masa4
i think you db name defaultly is qt_sql_default_connectionQSqlDatabase::removeDatabase("qt_sql_default_connection");
try this