Invalid QSqlRecord after performing another query to DB - c++

Here is the code:
QSqlQuery q1(db_connection), q2(db_connection);
q1.exec("SELECT * from users");
while(q1.next())
{
q2.exec("delete from table1");
if (!q2.isValid())
qDebug() << "q2 is not valid";
if (q1.isActive() && q1.isValid())
qDebug() << q1.record();
}
q1 is the correct query.
q2 is KNOWINGLY wrong one, cuz there is no table with name "table1".
The deal is: why q1 returns wrong (empty) data with QSqlQuery::record() method, but absolutely right data with QSqlQuery::value() method after q2 is beeing exec()'d?

Related

Query in QT doesn't get any data

This is rows in my table.
With this code, I get "in" in console.
QSqlQuery qry;
qry.prepare("SELECT * FROM user");
qry.exec();
if(qry.size() > 0)
qInfo() << "in";
else
qInfo() << "error";
But with this code, I get "error".
QSqlQuery qry;
qry.prepare("SELECT age FROM user");
qry.exec();
if(qry.size() > 0)
qInfo() << "in";
else
qInfo() << "error";
Try
QSqlQuery qry;
qry.prepare("SELECT age FROM \"user\"");
qry.exec();
The problem is with the table name. Since user is a reserved word, some tools (PgAdmin) automatically add double quotes to the name "user" and you have to use double quotes when applying to the table. Unfortunately user in Postgres is a function (equivalent to current_user) hence the first query returns a row without error.
The best solution is to rename the table and not use reserved words as Postgres identifiers (the name of a table, column, view, function, etc).
QSqlQuery qry;
qry.prepare("SELECT age FROM user");
if(qry.exec()) {
while(qry.next()) {
qInfo()<<"in";
}
} else {
qInfo()<<"error";
}

QSqlQuery forbid non-SELECT query

I'm looking for a way to forbid non-SELECT query for a QSqlQuery object.
I know QSqlQuery::isSelect is only effective after QSqlQuery::exec (damage
already done here).
So, is there any way to do that or I have to verify the query string explicitly.
Thanks.
From my experience, the QSqlQuery::isSelect function works well even before running the QSqlQuery::exec command. But only when the object is initialized with the query. i.e:
QSqlQuery query("SELECT * FROM someTable");
qDebug() << query.isSelect(); //Outputs True
OR
QString queryString = "SELECT * FROM someTable";
QSqlQuery query(queryString);
qDebug() << query.isSelect(); //Outputs True
If you are using the prepare function and passing the query string to it, then you will have to verify the query string yourself. i.e;
QSqlQuery query;
query.prepare("SELECT * FROM someTable");
qDebug() << query.isSelect(); //Outputs False
If you really want to avoid manual verification of the query string, you will have to avoid using QSqlQuery::prepare and QSqlQuery::bindValue functions and instead create the query yourself and initialize the QSqlQuery object with the QString you create.

SQLITE out of memory Unable to execute statement

I tried using sqlite in qt but I’ve come across an error.
qDebug() << QSqlDatabase::drivers();
QSqlDatabase DB = QSqlDatabase::addDatabase("QSQLITE");
DB.setDatabaseName("/Volumes/MAJID/majid/Naminic/db0.db");
QSqlQuery createQuery;
qDebug()<< "open: " << DB.open();
createQuery.exec("CREATE TABLE contact(name,tell)");
qDebug() << createQuery.lastError().text();
qDebug() << "insert : " << createQuery.exec("insert into contact(name,tell) values('a','b')");
qDebug() << createQuery.lastError().text();
and this is the out put of the debug :
(“QSQLITE”, “QODBC3”, “QODBC”)
open: true
out of memory Unable to execute statement
insert : false
out of memory Unable to execute statement
A couple problems I see that should get this working.
1. You need to pass the database object to the QSqlQuery when you create it.
The below line is wrong
QSqlQuery createQuery;
Change it to the following and you should be good
QSqlQuery createQuery(DB);
2. You need to open the database before you create the QSqlQuery object. The connection to the database needs to be open if you initialize the QSqlQuery object with it. So instead of this:
QSqlQuery createQuery(DB);
qDebug()<< "open: " << DB.open();
do this
qDebug()<< "open: " << DB.open();
QSqlQuery createQuery(DB);
That should get things working.
open database before set the query(db) works for me.
add this to the head.
if(!db.isOpened()) db.open();
if(db.isOpenError()) return false;

Qt Sqlite table column appears to be gone

QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName(":temp:");
if (!db.open()) {
qDebug() << "Database open error." << db.lastError();
return;
}
QSqlQuery query(db);
query.prepare("create table if not exists dew (id int, title varchar(255) not null)");
if (!query.exec()) {
qDebug() << "Query exec error. " << query.lastError();
return;
}
qDebug() << "Insert query exec OK";
if (!query.exec("insert into dew(id, title) values (1, 'hello')")) qDebug() << query.lastError();
Shows the output as
Insert query exec OK
QSqlError(1, "Unable to execute statement", "table dew has no column named id")
Insertion finished.
Table creation seems to be OK. But where is id field? I'm confused with this code. I test query.record().contains("id"); and it is false
":temp:" is not a valid name for a temporary database, this creates a regular database on disk which stays after the database connection is closed.
To create a temporary or an in-memory sqlite database, that won't be saved to a file, you need to pass respectively an empty string (*) or the special string ":memory:" as the database name.
http://www.sqlite.org/inmemorydb.html
Qt doesn't allow an empty QString as the database name, but a QString starting with a '\0' should work: db.setDatabaseName(QChar(0));

QSqlQuery not positioned on a valid record

I'm trying select a field of my date base, the code is:
if (db.db().isOpen())
{
qDebug() << "OK";
QSqlQuery query("SELECT state FROM jobs WHERE jobId = '553'", db.db());
qDebug() << query.value(0).toString();
}
else
qDebug() << "No ok";
The query is correct because when I do qDebug() << query.size;, it returns 1.
but with qDebug() << query.value(0).toString();, it returns:
OK
QSqlQuery::value: not positioned on a valid record
""
How can I fix it?
You should call query.first() before you can access returned data. additionally if your query returns more than one row, you should iterate via query.next().