Create sqlite table is not work - c++

I have a method that make a connection to SQLITE and work with database by conditions (insert data or create table in my database.)
When I call it in my code, at first open database correctly but can not create tables. Mean that query does not show error but not execute.
this is my method :
void SQL(string cmnd)
{
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");//not dbConnection
QString path = "DBAbsent";
db.setDatabaseName(path);
QSqlQuery q(db);
if(!db.open())
{
printf("Error to open database");
}
else
{
if (cmnd=="createTable")
{
q.prepare("create table IF NOT EXISTS Personel (P_id int primary key, "
"CardID varchar(50), "
"name varchar(50));");
if(!q.exec())
{
qDebug()<<strerror(errno);
qDebug()<<q.lastError(); // show this error : QSqlError("", "Unable to fetch row", "No query")
}
q.prepare("create table IF NOT EXISTS Absent "
"(P_id int , "
"DateTime varchar(50), "
"key1 int,key2 int,key3 int,key4 int);");
if(!q.exec())
qDebug()<<strerror(errno);
db.close();
return;
}
else if (cmnd=="Register")
{
string card=ReadFromCard();
printf("\nCard Accepted : %s\nEnter Your name: ",card.c_str());
string name;
int id;
//string dt=QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss");
cin>>name;
printf("\n Name Accepted.\nEnter Your Personel ID: ");
cin>>id;
q.prepare( "SELECT count(P_id) FROM Personel WHERE P_id =?;" );
q.bindValue(0,id);
if( !q.exec() )
{
printf("\nThe error occured from P_ID database");
qDebug()<<strerror(errno);
//ShowMainMenu();
//return;
}
// Note: if you don't return in case of an error, put this into the else{} part
while( q.next() )
{
if (q.value(0).toInt()>0)
{
printf("\nThis personel ID was repeated\n");
break;
}
else
{
q.prepare("SELECT CardID FROM Personel WHERE CardID =?;");
q.bindValue(0,card.c_str());
q.exec();
while(q.next())
{
printf("\nThis card is not valid : it was repeated\n");
break;
}
}
}
q.prepare("insert into Personel value(?,?,?);");
q.bindValue(0,id);
q.bindValue(1,card.c_str());
q.bindValue(2,name.c_str());
q.exec();
printf("\nInsert Personel complete\n");
db.close();
return;
}
else
{
string card;
card=cmnd;
QString dt=QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss");
q.prepare("SELECT P_id FROM Personel WHERE CardID =?;");
q.bindValue(0,card.c_str());
if( !q.exec() )
{
printf("\nThe error occured from database418\n");
ShowMainMenu();
}
string result=("\n CARD NOT VALID =>repeated %s\n");
// Note: if you don't return in case of an error, put this into the else{} part
while( q.next() )
{
int P_id = q.value(0).toInt();
q.prepare("insert into Absent(P_id,DateTime,key1,key2,key3,key4) value(?,?,1,0,0,0);");
q.bindValue(0,P_id);
q.bindValue(1,dt);
q.exec();
result=("\n********WELL COME **********%s\n");
}
printf("%s",result);
db.close();
return;
}
}
}
And this is my output :
0 - Press 0 to Back
1 - Press 1 to Register the card
1
//the below lines when I want to select something from both tables , occurred
No such file or directory
QSqlError("", "Unable to fetch row", "No query")
No such file or directory
//the below line is when the if(cmnd="Register") {..} block is running , occurred.
QSqlDatabasePrivate::addDatabase: duplicate connection name 'qt_sql_default_connection', old connection removed.

You don't need to close and open db connection every time SQL() function is running. Better approach is to open db once, when your app starts and close it at the end. Then, in SQL(..) you just create query like
QSqlQuery q;
and work with it.
Cause of QSqlError("", "Unable to fetch row", "No query") is that you create QSqlQuery(db); before db is opened. And you need to check q.prepare() for errors too.

It solved. Just do these :
1 - As #Tony said: QSqlQuery should defined after opening database.
2 - q.prepare just uses for SQL query contains bindvalue(), like select() or insert() .

Related

Error while executing query for Postgresql from Qt C++

I want to enter enter data from vector of objects into Postgresql table but it's not working. I establish connection to the database successfully, but the output returns an error -
QSqlError("42601", "QPSQL: Unable to create query", "ERROR: syntax error at end of input\nLINE 1: EXECUTE \n
My Code -
void MainWindow::WriteToDatabase()
{
// Establishing a connection to MySQL
database = QSqlDatabase::addDatabase("QPSQL");
database.setHostName("localhost");
database.setUserName("postgres");
database.setPassword("1234");
database.setDatabaseName("nz5_flightdatar");
bool test = QSqlDatabase::isDriverAvailable("QPSQL");
qDebug() << test << Qt::endl;
if(database.open())
{
sort(FlightList.begin(), FlightList.end());
vector<FlightData>::iterator itr;
ui->plainTextEdit->clear();
for (itr = FlightList.begin(); itr != FlightList.end(); itr++)
{
static int i = 0;
QString Time = QString::fromStdString(FlightList[i].getTime());
double Latitude = FlightList[i].getLatitude();
double Longitude = FlightList[i].getLongitude();
int Course = FlightList[i].getCourse();
int KTS = FlightList[i].getKTS();
int MPH = FlightList[i].getMPH();
int AltitudeFeet = FlightList[i].getAltitudeFeet();
QString ReportingFacility = QString::fromStdString(FlightList[i].getReportingFacility());
i++;
QSqlQuery query;
query.prepare("INSERT INTO 'public.flight_data' (Time, Latitude, Longitude, Course, KTS, MPH, AltitudeFeet, ReportingFacility)"
"VALUES (':time', ':latitude', ':longitude', ':course', ':kts', ':mph', ':altitudefeet', ':reportingfacility')");
query.bindValue(":time", Time);
query.bindValue(":latitude", Latitude);
query.bindValue(":longitude", Longitude);
query.bindValue(":course", Course);
query.bindValue(":kts", KTS);
query.bindValue(":mph", MPH);
query.bindValue(":altitudefeet", AltitudeFeet);
query.bindValue(":reportingfacility", ReportingFacility);
if(query.exec())
qDebug() << "success";
else
{
QMessageBox::information(this, "error", "No success");
qDebug() << query.lastError();
exit(0);
}
}
ui->statusbar->showMessage("Writing data to Database successful", 4000);
}
else
{
QMessageBox::warning(this, "Not connected", "Unable to connect to Database");
}
}
and the output -
qt.core.plugin.loader: In C:/Qt_Framework/6.4.1/mingw_64/plugins/sqldrivers/qsqlmysqld.dll:
Plugin uses incompatible Qt library (5.13.0) [debug]
true
QSqlError("42601", "QPSQL: Unable to create query", "ERROR: syntax error at end of input\nLINE 1: EXECUTE \n ^\n(42601)")
I am familiar with MySQL but I went crazy today trying to install drivers but failed miserably (read document and also a lot of StackOverflow threads), so I switched to Postgresql as Qt supports QPSQL.
Kindly help if you can.

How to write a prepared update query?

I've been trying to write an update function that takes the user to be updated(usr), the flag which then translates to the field to be updated and the new value. Here's the function,
bool DBManager::updateDB(User* usr, int flag, QVariant& value)
{
QSqlQuery query;
bool status = false;
QString temp_value = "";
QList<QString> fieldlist = {"First_Name", "Last_Name", "Email", "Username", "Password"};
QString field = fieldlist.at(flag);
if (field == "First_Name") {
usr->setFirstName(value.toString());
temp_value = usr->getFirstName();
} else if (field == "Last_Name") {
usr->setLastName(value.toString());
temp_value = usr->getLastName();
} else {
qDebug() << "invalid option";
}
query.prepare("UPADATE Users SET :field = :newValue WHERE Username = :Username");
query.bindValue(":field",field);
query.bindValue(":newValue",temp_value);
query.bindValue(":Username",usr->getUserName());
qDebug() << query.boundValues();
if (m_db.isOpen()){
if (query.exec()){
status = true;
qDebug() << "DATABASE:: Record update successful";
} else {
qDebug() << "DATABASE:: Record update unsuccessful - " << query.lastError();
}
} else {
qDebug() << "DATABASE:: not open ";
}
return status;
}
When I run the code I get an error. Here is the output:
QMap((":Username", QVariant(QString, "zielinkin1"))(":field", QVariant(QString, "Last_Name"))(":newValue", QVariant(QString, "Thibos")))
DATABASE:: Record update unsuccessful - QSqlError("", "Parameter count mismatch", "") User not updated DATABASE:: database closed
How to fix this?
Cause
First problem
It is not hard to guess, that value binding works only for values, not for field names.
For more info, please read about Inserting, Updating, and Deleting Records.
Second problem
Found by #JimCastro:
You have a typo in your query. UPADATE should be UPDATE.
Solution
Use a string concatenation to form your prepared query.
Example
Instead of
query.prepare("UPDATE Users SET :field = :newValue WHERE Username = :Username");
write
query.prepare("UPDATE Users SET " + field + " = :newValue WHERE Username = :Username");
Delete or comment this line
query.bindValue(":field",field);

The QSqlQuery returns exceptions for the words starting with some digits

I have this code:
foreach (QString TheKeyword, KeywordsList) {
if (!TheKeyword.isEmpty())
{
TheKeyword.replace("'","''").replace("[", "[[]");
QString sQuery = QString("UPDATE news SET deleted = '1' WHERE %1 like '%%2%' AND Id IN(%3) AND deleted = '0'")
.arg(TheColumn)
.arg(TheKeyword)
.arg(TheIDs);
QSqlQuery TheQuery(TheDB);
TheQuery.prepare(sQuery);
TheQuery.exec();
if (TheQuery.lastError().isValid())
{
qDebug() << TheQuery.lastError() << " - " << TheKeyword;
}
}
}
For example, the "KeywordsList" contains this word's list (The "KeywordsList" is a QStringList):
1Tap
World
A man from Mars
2 Battery
2Do
1CLICK
01 Net
2 Bananas
4 Bananas
system app remover
My code returns this errors:
QSqlError("", "Unable to fetch row", "No query") - "1Tap"
QSqlError("", "Unable to fetch row", "No query") - "2 Battery"
QSqlError("", "Unable to fetch row", "No query") - "2Do"
QSqlError("", "Unable to fetch row", "No query") - "1CLICK"
QSqlError("", "Unable to fetch row", "No query") - "01 Net"
QSqlError("", "Unable to fetch row", "No query") - "2 Bananas"
So, I see that problem is only with the keywords starting with '0', '1' or '2'
I tried to use bindValue, but without success.
Thank you.

QMYSQL query failing

I'm currently working on my project within C++ using Qt. I have MySQL as database storage and the idea is to make a small messenger like MSN and Skype.
However, my MySQL queries are failing. It simply gets no results or gives me an error. There's loads of code coming up, I'm sorry for that.
This is my mysql.cpp which creates and opens the database connection:
#include "mysql.h"
mysql::mysql()
{
this->db = QSqlDatabase::addDatabase("QMYSQL", "QMYSQL");
this->db.setHostName("localhost");
this->db.setUserName("root");
this->db.setPassword("Eequi4");
this->db.setDatabaseName("test");
this->db.open();
}
mysql::~mysql()
{
}
mysql_result mysql::create_result(QString query)
{
return mysql_result(this->db.exec(query));
}
QSqlError mysql::error()
{
return this->db.lastError();
}
The connection is opened. That works correctly.
This is my mysql_result.cpp, the file I use to add parameters, insert, get results etc:
#include "mysql_result.h"
mysql_result::mysql_result(QSqlQuery query)
{
this->query = query;
}
void mysql_result::add_parameter(QVariant value)
{
this->query.addBindValue(value);
}
void mysql_result::add_parameter(QString key, QVariant value)
{
this->query.bindValue(key, value);
}
int mysql_result::get_last_id()
{
return this->query.lastInsertId().toInt();
}
void mysql_result::execute()
{
this->query.execBatch();
}
QSqlQuery mysql_result::get_query()
{
return this->query;
}
mysql_result::~mysql_result()
{
}
Okay, this should work. If I have the following code, it correctly returns all member first_name's from the database:
mysql_result res = _mysql->create_result("SELECT * FROM members");
QSqlQuery qry = res.get_query();
while (qry.next())
{
qDebug() << qry.value("first_name");
}
In member_controller.cpp (the class I use to retrieve members by name/id), I got this:
member* member_controller::get_member(int id)
{
mysql_result result = engine::get_mysql().create_result("SELECT * FROM members WHERE member_id = :ID");
result.add_parameter(":ID", id);
QSqlQuery query = result.get_query();
if (query.exec() && query.next())
{
return new member(id, query.value("first_name").toString(), query.value("second_name").toString(), query.value("screen_name").toString(), query.value("email").toString(), query.value("status").toString());
}
else
{
qDebug() << engine::get_mysql().error() << "\n";
qDebug() << query.lastError() << "\n";
}
return new member(0, "", "", "", "", "");
}
What it does it will go to the else, and I get the error invalid syntax near :ID. If I replace :ID with #ID (just like in C#), it will go to the else without error code.. I don't know what the problem is.
Two things. The code needs to be optimized a bit and made easier, I'm gonna work on that. Also, is it possible/allowed to put code in a pastebin and paste the URL rather than put the code here?
Try changing your query to this:
"SELECT * FROM members WHERE member_id = ?"
and add your param like this:
result.add_parameter(0, id);
I'd also suspect, if (query.exec() && query.next()) is incorrect, and the check for .next() should be removed as I'd imagine that requires another record to exist in the result set.

SQLite Stops at 252 Entries

So I've written some C++ code to select data from one database and INSERT it into another. There's over 50,000 entries in the source db. The table definitions for the destination database are as follows:
CREATE TABLE evidence_master
( id INTEGER NOT NULL,
person_id TEXT NOT NULL,
message TEXT,
eid INTEGER NOT NULL,
frequency INTEGER,
string TEXT,
CONSTRAINT id_pk PRIMARY KEY (id),
CONSTRAINT eid_fk FOREIGN KEY (eid) REFERENCES evidences(eid)
);
CREATE TABLE evidences
(
eid INTEGER NOT NULL,
evidence_name TEXT,
CONSTRAINT eid_pk PRIMARY KEY (eid)
);
The source database is the one found here: http://wing.comp.nus.edu.sg/SMSCorpus/
My problem is, when it gets to the 252nd entry, it claims it cannot open the database (EDIT: the destination database). Despite having performed the work on 251 entries successfully.
Why might this be happening?
EDIT: here's the code that selects from the source:
dbOpenFail=sqlite3_open("../../../db/smscorpus.db", &dbCorpus);
if(dbOpenFail)
{
cerr << "Can't open sms corpus: " << sqlite3_errmsg(dbCorpus);
}
if(sqlite3_prepare(dbCorpus,
queryCorpus.data(),
queryCorpus.length() + 1,
&preparedCorpusQuery, NULL) != SQLITE_OK)
{
cerr << "Failed to prepare corpus query: " << queryCorpus << zErrMsg << endl;
sqlite3_free(zErrMsg);
}
rowSelectCorpus=sqlite3_step(preparedCorpusQuery);
while(rowSelectCorpus != SQLITE_DONE) //need to go through 51652 messages from corpus
{
if(rowSelectCorpus == SQLITE_ROW)
{
personID = sqlite3_column_text(preparedCorpusQuery, 0); //get sender ID
messageContent = sqlite3_column_text(preparedCorpusQuery, 1); //get message itself
db_entry d1(string(reinterpret_cast<const char *>(personID)),
string(reinterpret_cast<const char *>(messageContent)));
insertResult = d1.insertIntoDatabase();
if(insertResult == -1)
{
return 0; //exit
}
}
rowSelectCorpus=sqlite3_step(preparedCorpusQuery);
}
Some C runtime libraries have a default limit of 256 open file handles per process.
Apparently, your program is opening the database for every INSERT operation, and forgets to close it.
You should open every database only once.