query.next() returning false - sql

I have used the query.next() function inside my code, but its returning false.
I even checked in the database, there are 4 records present. But the code shows only one.
However if i use query.next() before the code of query.valid() then it doesn't show any record
Please help
qDebug() << "entering payment: get all the unchecked invoices for user: " + user;
QStringList tmp;
QSqlQuery query(m_storageUserManager->database());
m_storageUserManager->dumpTable(m_invoiceInfoTable);
m_storageUserManager->dumpTable(m_invoiceUserTable);
qDebug()<<"THE NAME OF THE INVOICE USER TABLE_----=-----------------"<<m_invoiceInfoTable;
qDebug()<<"THE NAME OF THE INVOICE USER TABLE_----=-----------------"<<m_invoiceUserTable;
query.prepare("SELECT invoice FROM "+ m_invoiceInfoTable +" WHERE invoice = (SELECT
invoice FROM "+ m_invoiceUserTable +" WHERE user=:user)");
// query.prepare("SELECT invoice FROM " + m_invoiceInfoTable + ","+ m_invoiceUserTable +" WHERE " + m_invoiceInfoTable + ".user = " + m_invoiceUserTable + ".:user");
query.bindValue(":user", user);
query.exec();
query.first();
qDebug()<<"Unchecked invoices done!!! " ;
if(query.isValid()) {
do {
tmp.append(query.value(0).toString()); //as the value returned by value() is a QVariant so we need to change it to String.
} while(query.next());
} else
tmp.append("No Unchecked invoice in the database");
return tmp;

To check if the query was successful you should test the return value of either QSqlQuery::exec() or QSqlQuery::isActive() before trying to call first/next/last (when you pass the query string to the constructor of QSqlQuery, the query is already executed, so, you need to use QSqlQuery::isActive()).
first(), next() and last() return true if they positioned the query on a valid record, you don't have to test isValid() separately. Since first() is a positioning function too, you can read the value without calling next() directly after, unless you want to skip the first record.
Since you may want to add fields from the the "invoice-info" table to your query, I kept the subquery (with IN instead of = as Mat already answered in the comment).
query.prepare(QString("SELECT invoice FROM %1 WHERE invoice "
"IN (SELECT invoice FROM %2 WHERE user=:user)")
.arg(m_invoiceInfoTable, m_invoiceUserTable));
/*
// Or with an inner join
query.prepare(QString("SELECT %1.invoice FROM %1 "
"INNER JOIN %2 ON %1.invoice = %2.invoice "
"WHERE user=:user").arg(m_invoiceInfoTable, m_invoiceUserTable));*/
query.bindValue(":user", user);
if (!query.exec()) {
tmp.append("Query error: %1" + query.lastError().text());
} else if (!query.first()) {
tmp.append("No Unchecked invoice in the database");
} else {
do {
tmp.append(query.value(0).toString());
} while(query.next());
}

Try
query.prepare("SELECT invoice FROM " + m_invoiceInfoTable + " WHERE user=:user");

Related

SQLite error in QT - QSqlError("", "Parameter count mismatch", "")

I'm trying to simply count the amount of records that has a 'true' status.
this is the SQLite table structure:
CREATE TABLE Suppliers(ID INTEGER PRIMARY KEY AUTOINCREMENT,Name varchar(50),Number varchar(15),URL varchar(70),Status bool,ShippingCost integer)
I am then calling a query from QT as follows:
int SQLiteController::ActiveSupplierCount()
{
int count = 0;
QSqlQuery Query;
Query.prepare("SELECT *"
"FROM Suppliers"
"WHERE Status = (:Status)");
Query.bindValue(":Status", true);
Query.exec();
qDebug() << Query.lastError();
while(Query.next() == true)
{
count++;
}
qDebug() << count;
return count;
};
The last error returned here is "Parameter count mismatch"
and I cannot figure out why... There is only 1 parameter, and I assign to that 1 parameter.
Try to add some extra spaces after each line of your query like this
Query.prepare("SELECT * "
"FROM Suppliers "
"WHERE Status = (:Status)");

Sqlite Update query with SqliteModernCpp

I am using the SqliteModernCpp library. I have a data access object pattern, including the following function:
void movie_data_access_object::update_movie(movie to_update)
{
// connect to the database
sqlite::database db(this->connection_string);
// execute the query
std::string query = "UPDATE movies SET title = " + to_update.get_title() + " WHERE rowid = " + std::to_string(to_update.get_id());
db << query;
}
Essentially, I want to update the record in the database whose rowid (the PK) has the value that the object to_update has in its parameter (which is returned by get_id()).
This code yields an SQL logic error. What is the cause of this?
It turned out single quotes (') within the query string being created were missing. The line should be:
std::string query = "UPDATE movies SET title = '" + to_update.get_title() + "' WHERE rowid = " + std::to_string(to_update.get_id());
Since there is no UPDATE example in the official docs on github, This is how UPDATE queries should be implemented with prepared statements and binding
#define MODERN_SQLITE_STD_OPTIONAL_SUPPORT
#include "sqlite_modern_cpp.h"
struct Book {
int id;
string title;
string details;
Book(int id_, string title_, string details_):
id(std::move(id_)),
title(std::move(title_)),
details(std::move(details_)) {}
}
int main() {
Book book = Book(0, "foo", "bar")
sqlite::database db("stackoverflow.db");
// Assuming there is a record in table `book` that we want to `update`
db <<
" UPDATE book SET "
" title = ?, "
" details = ? "
" WHERE id = ?; "
<< book.title
<< book.details
<< book.id;
return 0;
}

Return a value from SQL Query Qt

I am trying to return a value from SQL Query. When logging in, 'Type' is a value in the database, 1,2 or 3. username and password are QStrings in the code.
In my attempt, this returns the wrong value (just a 1)
int userrole = roleQry.exec("SELECT Type FROM [tss_people] WHERE Username=\'" + username + "' AND Password='" + password + "'");
qDebug() << userrole;
QSqlQuery::exec() returns a status, i.e. whether the query was successfully executed or not.
Results can be optained by iterating over the query
while(roleQry.next()) {
qDebug() << roleQry.value(0).toInt();
}

Inserting data through GUI into sql server

I'm able to execute sql statements by writing the sql codes (Insert etc) on Eclipse and it is being displayed into sql server correctly. Connection has been done. But what should I do when a user wants to add data through a GUI interface (text field) and the data need to get stored into the database automatically ??
my code in the ADD button, but i'm getting the Error: java.lang.NullPointerException ! Help please..
try {
String pid = ProductID.getText();
String sql = "insert into Products_tbl values (' " +pid + " ')";
// Running the sql query
rs = st.executeQuery(sql);
int count = 0;
while (rs.next()) {
count = count + 1;
}
if (count == 1) {
JOptionPane.showMessageDialog(null, "Welcome");
}
else if (count > 1) {
JOptionPane.showMessageDialog(null,"Duplicate User Access Denied");
}
else {
JOptionPane.showMessageDialog(null, " User Not Found ");
}
}
catch (Exception ex) {
System.out.println("Error: " + ex);
}
1- Using (' " +pid + " ')" is not safe because SQL injection may occur. Use SqlParameters instead. Please check:
https://www.w3schools.com/sql/sql_injection.asp
2- I am pretty sure something is wrong with the line: rs = st.executeQuery(sql);
Here, I bet the value of st is null. Make sure that your connection variable is defined and set correctly and you created the statement like below:
st = connection.createStatement();
You can also try executeupdate(query) instead of executequery(query) like:
int flag = st.executeUpdate(query);
Ref: https://docs.oracle.com/javase/7/docs/api/java/sql/Statement.html#executeUpdate%28java.lang.String%29
3- Please use printStackTrace() method while printing the error in the catch blog, the error message would be more understandable.
System.out.println("Error: " + ex.printStackTrace());

sqlite / websql: separate queries produce different results than join queries

I have a very simple db that has two tables, one to store a user's auth (username and pw) and one to store preferences. Currently when my app initializes, it checks for settings first and then auth. But I want to grab it all at once. The way the app is designed, there is only ever 1 record in either table, so I don't use WHERE clauses in my queries.
The problem is, when I do queries separately, they give different results than if I join them.
Consider this scenario: a user logs in, sets some settings and then logs out. In may app this causes the auth table to be cleared but the settings remain intact.
Sign-out query (just clears auth table)
db.transaction(function(tx) {
tx.executeSql('DELETE FROM userdata');
}, errorDB);
However this outputs "0 rows found":
db.transaction(function(tx) {
tx.executeSql('SELECT USERDATA.*, PREFS.* FROM USERDATA, PREFS', [], function (tx, results) {
var len = results.rows.length;
console.log(len + " rows found.");
for (var i=0; i<len; i++){
console.log("Row = " + i + " ID = " + results.rows.item(i).id + " Data = " + results.rows.item(i));
}
}, errorDB);
}, errorDB);
Whereas this outputs a row:
db.transaction(function(tx) {
tx.executeSql('SELECT * FROM PREFS', [], function (tx, results) {
var len = results.rows.length;
console.log(len + " rows found.");
for (var i=0; i<len; i++){
console.log("Row = " + i + " ID = " + results.rows.item(i).id + " Data = " + results.rows.item(i));
}
}, errorDB);
}, errorDB);
Even if there is no auth shouldn't the join query find the prefs data? What's going on here?
When you list two tables A and B in the FROM clause, you get a cross join, which returns A×B records.
So if one table is empty, the result will be empty, too.
To ensure that you have a record even for an empty table, add another record with UNION ALL, then use LIMIT 1 return the first record.
For example,
SELECT Name, PW FROM UserData
UNION ALL
SELECT NULL, NULL
LIMIT 1
will return either a single record with the name/password, or a single record with two NULL values.
To join that with the other table, use a subquery:
SELECT *
FROM (SELECT Name, PW FROM UserData
UNION ALL
SELECT NULL, NULL
LIMIT 1),
Prefs