How to get the correct QSqlError?
-
Here's what I've got in the UI:

The topleft segment is
ObjectsView, topright isQueryResultView, in between those isQueryViewand at bottom theLogView. Logs inLogViewis in last in first order.dbis anextern QSqlDatabase db;initialized in the constructor of theObjectsViewand is used inObjectsViewandQueryResultView.So when I first attached the
MakeFileas the database, theObjectsViewexecuted this:void ObjectsView::openFileDialog() { ... db.setDatabaseName(dialog.selectedFiles().first()); if(!db.open()) return; emit logMessage(db.lastError()); QSqlQuery query("SELECT * FROM sqlite_master", db); query.setForwardOnly(true); if(query.exec()){...} else emit logMessage(query.lastError()); ... }logMessage(...)signal is consumed byonMessageReceivedslot ofLogViewthis way:void LogView::onMessageReceived(const QSqlError &msg) { auto cursor = box->textCursor(); cursor.movePosition(QTextCursor::Start); auto time = QDateTime::currentDateTime().toString("hh:mm:ss AP"); QString log(time + " : "); switch (msg.type()) { case QSqlError::NoError: log += "No error : " + msg.text(); break; case QSqlError::ConnectionError: log += "Connection error : " + msg.text(); break; case QSqlError::StatementError: log += "Statement error : " + msg.text(); break; case QSqlError::TransactionError: log += "Transaction error : " + msg.text(); break; case QSqlError::UnknownError: log += "Unknown error : " + msg.text(); break; } cursor.insertText(log + '\n'); }why does it get into this line
emit logMessage(db.lastError());inObjectsViewwhen I provide it an invalid database file and why does it sayNoError? With thatMakeFileas the database when I clicked the play button ofQueryView, theQueryResultViewin a slot executed this:void QueryResultView::executeQuery(const QString &query) { if(!db.open()) return; emit logMessage(db.lastError()); model->setQuery(query, db); while (model->canFetchMore()) model->fetchMore(); db.close(); emit logMessage(model->query().lastError()); table->setModel(model); //EDIT: this line isn't necessary, it should be in the constructor of the view }both
emit logMessage(db.lastError())andemit logMessage(model->query().lastError())said no error! How to get the correct error message?One more side question, the model in the
QueryResultViewis aQSqlQueryModeland the table is aQTableView. Whenever I click the play blutton or hitF5inQueryView, that piece of code inQueryResultViewis executed. Do I have to have somedeleteoperation onmodelandtable, if so, how?, or the Qt Framework will do that automatically? -
Here's what I've got in the UI:

The topleft segment is
ObjectsView, topright isQueryResultView, in between those isQueryViewand at bottom theLogView. Logs inLogViewis in last in first order.dbis anextern QSqlDatabase db;initialized in the constructor of theObjectsViewand is used inObjectsViewandQueryResultView.So when I first attached the
MakeFileas the database, theObjectsViewexecuted this:void ObjectsView::openFileDialog() { ... db.setDatabaseName(dialog.selectedFiles().first()); if(!db.open()) return; emit logMessage(db.lastError()); QSqlQuery query("SELECT * FROM sqlite_master", db); query.setForwardOnly(true); if(query.exec()){...} else emit logMessage(query.lastError()); ... }logMessage(...)signal is consumed byonMessageReceivedslot ofLogViewthis way:void LogView::onMessageReceived(const QSqlError &msg) { auto cursor = box->textCursor(); cursor.movePosition(QTextCursor::Start); auto time = QDateTime::currentDateTime().toString("hh:mm:ss AP"); QString log(time + " : "); switch (msg.type()) { case QSqlError::NoError: log += "No error : " + msg.text(); break; case QSqlError::ConnectionError: log += "Connection error : " + msg.text(); break; case QSqlError::StatementError: log += "Statement error : " + msg.text(); break; case QSqlError::TransactionError: log += "Transaction error : " + msg.text(); break; case QSqlError::UnknownError: log += "Unknown error : " + msg.text(); break; } cursor.insertText(log + '\n'); }why does it get into this line
emit logMessage(db.lastError());inObjectsViewwhen I provide it an invalid database file and why does it sayNoError? With thatMakeFileas the database when I clicked the play button ofQueryView, theQueryResultViewin a slot executed this:void QueryResultView::executeQuery(const QString &query) { if(!db.open()) return; emit logMessage(db.lastError()); model->setQuery(query, db); while (model->canFetchMore()) model->fetchMore(); db.close(); emit logMessage(model->query().lastError()); table->setModel(model); //EDIT: this line isn't necessary, it should be in the constructor of the view }both
emit logMessage(db.lastError())andemit logMessage(model->query().lastError())said no error! How to get the correct error message?One more side question, the model in the
QueryResultViewis aQSqlQueryModeland the table is aQTableView. Whenever I click the play blutton or hitF5inQueryView, that piece of code inQueryResultViewis executed. Do I have to have somedeleteoperation onmodelandtable, if so, how?, or the Qt Framework will do that automatically?@Emon-Haque said in How to get the correct QSqlError?:
if(!db.open()) return;
emit logMessage(db.lastError());This is wrong - open() returns false in case of error, then you should emit the error...
-
@Emon-Haque said in How to get the correct QSqlError?:
if(!db.open()) return;
emit logMessage(db.lastError());This is wrong - open() returns false in case of error, then you should emit the error...
@jsulm, it didn't catch error, it opened an invalid file ie, the
MakeFileas database. -
@jsulm, it didn't catch error, it opened an invalid file ie, the
MakeFileas database.@Emon-Haque Doesn't change the fact that this part of your code is logically wrong.
Qith SQLite you will not get an error as far as I know if the file is not there. Not sure what happens if the file exists but is not a database file. -
@jsulm, it didn't catch error, it opened an invalid file ie, the
MakeFileas database.@Emon-Haque said in How to get the correct QSqlError?:
it didn't catch error
Evidently SQLite does not consider/report an error at the time of opening a file, whatever it contains. Only later when it tries to perform some SQL operation on it does it complain.
-
@Emon-Haque Doesn't change the fact that this part of your code is logically wrong.
Qith SQLite you will not get an error as far as I know if the file is not there. Not sure what happens if the file exists but is not a database file.@jsulm, yes that's obviously wrong and thanks for reminding me about that. Before posting topic, I try to make it compact. If I'd done it in correct way, I'd have to add some extra lines, braces, etc.
-
@Emon-Haque said in How to get the correct QSqlError?:
it didn't catch error
Evidently SQLite does not consider/report an error at the time of opening a file, whatever it contains. Only later when it tries to perform some SQL operation on it does it complain.
@JonB, when I call
model->fetchMore, where model is aQSqlQueryModel, with an invalid file, I getfile is not a database Unable to execute statementif I give it some string, If I give it an empty string, it saysNo Error.With
QSqlQuery query("SELECT * FROM sqlite_master", db);inObjectsView, I got connection error and a messageNo query Unable to fetch row. Can I get the same message I got withQSqlQueryModelwhen it's an invalid file and I gave it some string? -
@JonB, when I call
model->fetchMore, where model is aQSqlQueryModel, with an invalid file, I getfile is not a database Unable to execute statementif I give it some string, If I give it an empty string, it saysNo Error.With
QSqlQuery query("SELECT * FROM sqlite_master", db);inObjectsView, I got connection error and a messageNo query Unable to fetch row. Can I get the same message I got withQSqlQueryModelwhen it's an invalid file and I gave it some string?@Emon-Haque
Well, to an extent you get whatever you get as error messages, I know no more than that!However:
model->setQuery(query, db); while (model->canFetchMore()) model->fetchMore();You do not check the result from
setQuery()before you proceed tocanFetchMore(). Per void QSqlQueryModel::setQuery(const QString &query, const QSqlDatabase &db = QSqlDatabase()):lastError() can be used to retrieve verbose information if there was an error setting the query.
So you should check
model->lastError()immediately after thesetQuery()? -
@Emon-Haque
Well, to an extent you get whatever you get as error messages, I know no more than that!However:
model->setQuery(query, db); while (model->canFetchMore()) model->fetchMore();You do not check the result from
setQuery()before you proceed tocanFetchMore(). Per void QSqlQueryModel::setQuery(const QString &query, const QSqlDatabase &db = QSqlDatabase()):lastError() can be used to retrieve verbose information if there was an error setting the query.
So you should check
model->lastError()immediately after thesetQuery()?@JonB, will try that after a break and, hopefully, will let you know what happens.
-
@Emon-Haque
Well, to an extent you get whatever you get as error messages, I know no more than that!However:
model->setQuery(query, db); while (model->canFetchMore()) model->fetchMore();You do not check the result from
setQuery()before you proceed tocanFetchMore(). Per void QSqlQueryModel::setQuery(const QString &query, const QSqlDatabase &db = QSqlDatabase()):lastError() can be used to retrieve verbose information if there was an error setting the query.
So you should check
model->lastError()immediately after thesetQuery()?@JonB, Here's what it does:

First, I gave it an invalid database and theseQSqlQuery query("SELECT * FROM sqlite_master", db); if(query.exec()) ... else emit logMessage(query.lastError());gave me
08:14:41 PM : Connection error : No query Unable to fetch row, the error message is incorrect. There was query BUT the database file is invalid. Second, I clicked the play button and in the box there was no text and thesemodel->setQuery(query, db); emit logMessage(model->lastError()); while (model->canFetchMore()) model->fetchMore();gave me
08:14:48 PM : No error :, it's also incorrect. Both the database is invalid and there was no query. Third, I gaveSELECTas the query and it gave me08:14:56 PM : Statement error : incomplete input Unable to execute statement. In this case it didn't say anything about the validity of database.EDIT
After a while I gave itSELECT * FROM x, with that invalidMakefileas database, it gave me09:55:22 PM : Statement error : file is not a database Unable to execute statement.So you see the variations in
QSqlError. In all of those cases I should get a single message likeSQLite error 26: 'file is not a database' -
@JonB, Here's what it does:

First, I gave it an invalid database and theseQSqlQuery query("SELECT * FROM sqlite_master", db); if(query.exec()) ... else emit logMessage(query.lastError());gave me
08:14:41 PM : Connection error : No query Unable to fetch row, the error message is incorrect. There was query BUT the database file is invalid. Second, I clicked the play button and in the box there was no text and thesemodel->setQuery(query, db); emit logMessage(model->lastError()); while (model->canFetchMore()) model->fetchMore();gave me
08:14:48 PM : No error :, it's also incorrect. Both the database is invalid and there was no query. Third, I gaveSELECTas the query and it gave me08:14:56 PM : Statement error : incomplete input Unable to execute statement. In this case it didn't say anything about the validity of database.EDIT
After a while I gave itSELECT * FROM x, with that invalidMakefileas database, it gave me09:55:22 PM : Statement error : file is not a database Unable to execute statement.So you see the variations in
QSqlError. In all of those cases I should get a single message likeSQLite error 26: 'file is not a database'@Emon-Haque
All I can say is mostly/frequently/probably those errors come from SQLite, or maybe the SQLite driver, not Qt. -
These errors also vary depending on which object I'm using (
QSqlQueryModelorQSqlQuery) and with a valid database. Here's the error I got withQSqlQueryModel:
To code is:
else{ QSqlQueryModel sqlQuery; bool gotError = false; db.transaction(); for (int i = 0; i < statements.size(); i++) { auto trimmed = statements[i].trimmed(); if(trimmed.startsWith("--")) continue; sqlQuery.setQuery(trimmed); if(sqlQuery.query().isSelect()){ emit widget->logMessage("e,SELECT isn't allowed while executing multiple statements"); gotError = true; break; } else if(sqlQuery.query().lastError().type() != QSqlError::NoError){ emit widget->logMessage("e," + sqlQuery.query().lastError().text()); gotError = true; break; } } ... }so it's correct,
NewTableexists. If I replace those code with these:else{ bool gotError = false; db.transaction(); for (int i = 0; i < statements.size(); i++) { auto trimmed = statements[i].trimmed(); if(trimmed.startsWith("--")) continue; sqlQuery.clear(); sqlQuery.prepare(trimmed); sqlQuery.exec(); if(sqlQuery.isSelect()){ emit widget->logMessage("e,SELECT isn't allowed while executing multiple statements"); gotError = true; break; } else if(sqlQuery.lastError().type() != QSqlError::NoError){ emit widget->logMessage("e," + sqlQuery.lastError().text()); gotError = true; break; } } ... }where
sqlQueryis a globalQSqlQuery, I get this error:
that's a misleading error I got! Am I doing something wrong or it's an issue with
SQLite?EDIT
Looks likeQSqlQuerydoesn't need to be executed to get error. I've to check error immediately aftersqlQuery.prepare(trimmed);and if there's no error then I should callsqlQuery.exec(). In a nutshell, Qt executes the query, and figures out the error, before I callexec.