Getting a QSqlError("", "", "") but the data is inserted - c++

I am programming a Stock Control Program in Qt but when im inserting data I receive an error of QSqlError("", "", ""). The problem is that the data is being inserted into the SQLITE database but I'm unsure of what error means.
The code that I'm using to insert data into the database is below:
query_Account.prepare("INSERT INTO Customer(Company_Name, City, Phone_Number, Street_Adress, County, BULSTAT, Company_Owner, Account_Since) "
"VALUES (:Company_Name, :City, :Phone_Number, :Street_Adress, :County, :BULSTAT, :Company_Owner, :Account_Since)");
query_Account.bindValue(":Company_Name", ui->lineEdit_Company_Name->text());
query_Account.bindValue(":City", ui->lineEdit_City->text());
query_Account.bindValue(":Phone_Number", (ui->lineEdit_Phone_Num->text()).toInt());
query_Account.bindValue(":Street_Adress", ui->lineEdit_Street_Add->text());
query_Account.bindValue(":County", ui->lineEdit_County->text());
query_Account.bindValue(":BULSTAT", (ui->lineEdit_BULSTAT->text()).toInt());
query_Account.bindValue(":Company_Owner", ui->lineEdit_Company_Owner->text());
query_Account.bindValue(":Account_Since", 1776-07-04);
query_Account.exec();
qDebug() << "SQL query_Account:" << query_Account.executedQuery();
qDebug() << "SQL ERROR:" << query_Account.lastError();

You're not in fact getting an error. You're just unconditionally printing out an error even if you didn't get one.
if (query_Account.exec()) {
// got no error, proceed
qDebug() << "Yay!";
} else {
// got an error, deal with it
qDebug() << query_Account.executedQuery();
qDebug() << query_Account.lastError();
}

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.

Running arbitrary SQL commands MySQL C++ (X DevAPI)?

I've connected my C++ project to MySQL and successfully created a session. I was able to create a Schema. My issue is that when I try to run simple arbitrary queries like USE testSchema SHOW tables; using the MySQL/C++ api, I run into SQL syntax errors. When I run the function directly in the MySQL shell, the query runs perfectly fine.
Here is the full code
const char* url = (argc > 1 ? argv[1] : "mysqlx://pct#127.0.0.1");
cout << "Creating session on " << url << " ..." << endl;
Session sess(url);
{
cout << "Connected!" << endl;
// Create the Schema "testSchema"; This code creates a schema without issue
cout << "Creating Schema..." << endl;
sess.dropSchema("testSchema");
Schema mySchema = sess.createSchema("testSchema");
cout << "Schema Created!" << endl;
// Create the Table "testTable"; This code runs like normal, but the schema doesn't show
cout << "Creating Table with..." << endl;
SqlStatement sqlcomm = sess.sql("USE testSchema SHOW tables;");
sqlcomm.execute();
}
Here is the console output:
Creating session on mysqlx://pct#127.0.0.1 ...
Connected!
Creating Schema...
Schema Created!
Creating Table with...
MYSQL ERROR: CDK Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SHOW tables' at line 1
The error You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SHOW tables' at line 1 is a MySQL error that means I have a syntax error in the query, but when I take a closer look at a query, I see there is nothing wrong with it.
I've copied and pasted the code directly from the cpp file into the mysql shell and it runs perfectly. This tells me that something is up with the formatting of how I'm entering the query in the sql() function. But the documentation for the sql() function is really terse and.
Here is the reference to the sql() function: https://dev.mysql.com/doc/dev/connector-cpp/8.0/class_session.html#a2e625b5223acd2a3cbc5c02d653a1426
Can someone please give me some insight on where I'm going wrong? Also here here is the full cpp code for more context:https://pastebin.com/3kQY8THC
Windows 10
Visual Studio 2019
MySQL 8.0 with Connect/C++ X DevAPI
You can do it in two steps:
sess.sql("USE testSchema").execute();
SqlStatement sqlcomm = sess.sql("SHOW tables");
SqlResult res = sqlcomm.execute();
for(auto row : res)
{
std::cout << row.get(0).get<std::string>() << std::endl;
}
Also, you can use the Schema::getTables():
for(auto table : mySchema.getTables())
{
std::cout << table.getName() << std::endl;
}
Keep in mind that the Schema::getTables() doesn't show the Collections created by Schema::createCollection(). There is also a Schema::getCollections():
for(auto collection : mySchema.getCollections())
{
std::cout << collection.getName() << std::endl;
}

Qt PL/SQL - Assignment Operator - Character String Buffer too small

I have been picking my brain for a while trying to figure this one out.
The problem I am having is that the function I am using in Oracle returns a BLOB. It's a list of items that are concatenated together using ||.
From the research I have done,
In the QSQLQuery docs it says "Stored procedures that uses the return statement to return values, or return multiple result sets, are not fully supported. For specific details see SQL Database Drivers." - which leads me to believe I may need to switch to a different codebase if Qt cannot handle it yet.
The documentation for the QOCI driver mentions this "Binary Large Objects (BLOBs) can be read and written, but be aware that this process may require a lot of memory. You should use a forward only query to select LOB fields (see QSqlQuery::setForwardOnly())."
I did set
query.setForwardOnly(true);
Before I prepared or executed the statement.
However, I still get this error
QSqlError("6502", "Unable to execute statement", "ORA-06502: PL/SQL: numeric or value error: character string buffer too small\nORA-06512: at line 55\n")
I had to scrub the code a bit, I hope this is still helpful to give context to what i'm trying to accomplish
temp_clob clob;
name varchar2(183) := ?;
start varchar2(16) := ?;
end varchar2(16) := ?;
count integer := ?;
return_val named_redacted_table_object; -- Sorry had to remove this, it's a table with more Date, Varchar, etc
begin
dbms_lob.createtemporary(temp_clob, true);
return_val := package_name.function_name (
set_name => name,
start_time => to_date(start, 'yyyy-mm-dd hh24:mi'),
end_time => to_date(end, 'yyyy-mm-dd hh24:mi'),
max_count => count);
-- In here was a loop that would break apart the removed table object and make it into strings along the following lines
-- '' || return_val(i).name || return_val(i).value || etc
-- and would store these into the CLOB / temp_clob
? := temp_clob;
end;
I could not get something as simple as this to work
begin
? := 'test123';
end;
With the assumption I could at least read this string in Qt.
Here is my code for Qt
QString name = "test";
QSqlQuery query(db);
query.setForwardOnly(true);
query.prepare(sql);
QString test_sql_text = ui->comboBox_test_text->currentText();
qDebug() << name;
query.bindValue(0, name);
query.bindValue(1, "2003-03-14 00:00");
query.bindValue(2, "2005-03-14 23:00");
query.bindValue(3, 2);
query.bindValue(4, QString(""), QSql::Out);
bool query_executed_ok = query.exec();
qDebug() << "did it execute?" << query_executed_ok;
// qDebug() << query.executedQuery();
qDebug() << query.boundValues();
qDebug() << query.lastError();
QSqlRecord rec = query.record();
qDebug() << rec;
int record_count = rec.count();
qDebug() << "Records: " << record_count;
while (query.next()) {
for(int i=0;i<record_count;i++) {
qDebug() << query.isValid() << " - " << rec.fieldName(i) << " " << query.value(i).toString();
}
}
The error posted appears to be from within the Oracle code; ORA.... You have stripped so much it's hard to see what is actually happening, especially the are where the error apparently occurred. But perhaps using Oracle supplied code that is specifically designed to handle CLOBs. Instead of
'' || return_val(i).name ...
Try
dbms_lob.append(temp_clob, to_clob(return_val(i).name))
begin
? := 'test123';
end;
Bind variables are used to assign values to variables. You define your variable in your pl/sql code and assign a value to it at runtime by using a bind variable. In that case pl/sql code will compile correctly.
In your code the bind variable is used to replace the pl/sql variable, not the value, which will fail. Your pl/sql block cannot be compiled because it cannot resolve the "?".
A valid use of bind variables would be
BEGIN
l_xyz := ?;
END;
where you assign the value test123 at runtime.
It took some fiddling, and I realize I gave fairly cryptic code. So thank you to belayer and Koen for taking a shot at my mess.
What I was able to determine and get working for anyone else running into this:
Let me start off by saying I am not sure if this is a bug, or if i'm doing something in a way that was not intended by the designers of QSqlQuery (The class for handling SQL calls).
The call would work in SQL developer and I would see the intended CLOB with all characters. I was unable to get DBMS_Output to work, however, I saw this post saying to reserve space on the string before binding it to the query.
It solves my issue and shows the result in the debug window. However, it presents a new problem. What if the string becomes larger than my hard coded reserve value?
Here's the updated code for that
query.prepare(sql);
QString name= ui->comboBox_name->currentText();
qDebug() << project;
query.bindValue(":name", project);
query.bindValue(":start_date", "2005-03-14 00:00");
query.bindValue(":end_date", "2006-03-14 23:00");
query.bindValue(":max_count", 3);
QString testStr ="*****";
//testStr.truncate(0); //Maybe this works too?
testStr.reserve( 1000000 ); // This did it for sure
qDebug() << testStr.capacity();
query.bindValue(":result_clob", testStr, QSql::Out);
bool query_executed_ok = query.exec();
qDebug() << "did it execute?" << query_executed_ok;
if (query_executed_ok) {
testStr = query.boundValue(":result_clob").toString();
qDebug() << testStr;
} else {
qDebug() << "string is empty";
}
I got the idea to do this, from THIS post.

Why Isn't find_one working in MongoDB C++?

I have a MongoDB 3.0.7 database, created with the mongo shell. The following works fine:
% mongo test
> vs = db.myCollection.findOne({"somefield.subfield": "somevalue"})
but when I do this in C++:
mongocxx::instance inst{};
mongocxx::client conn{};
auto db = conn["test"];
bsoncxx::stdx::optional< bsoncxx::document::value> docObj;
try {
docObj =
db["myCollection"]
.find_one(document{} <<
"somefield.subfield" << "someValue" <<
bsoncxx::builder::stream::finalize);
} catch (mongocxx::exception::operation e) {
std::cerr << "Retrieval failed (and exception thrown)";
}
if (docObj == bsoncxx::stdx::nullopt)
std::cerr << "Failed to find object";
I get "Failed to find object". What am I missing here?
Update: 11/23/2015, 10:00
I've installed the latest cxx driver (0.3.0), and made the following changes:
mongocxx::instance inst{};
mongocxx::client *connPtr;
bsoncxx::stdx::string_view connectionString("mongodb://localhost");
connPtr = new mongocxx::client(mongocxx::uri(connectionString));
auto db = connPtr->database("test");;
bsoncxx::stdx::optional< bsoncxx::document::value> docObj;
try {
docObj =
db["myCollection"]
.find_one(document{} <<
"somefield.subfield" << "someValue" <<
bsoncxx::builder::stream::finalize);
} catch (mongocxx::exception::operation e) {
std::cerr << "Retrieval failed (and exception thrown)";
}
if (docObj == bsoncxx::stdx::nullopt)
std::cerr << "Failed to find object";
I'm back to exactly the same thing. Calling db.list_collections(document{}) retrieves no results.
The bsoncxx library has two document types, views and values. A document::value contains the actual document data, and a document::view is just a reference to some underlying value. Values must outlive the views that use them.
There's a bug in the new c++11 driver with how document::values are passed around. This code produces a document::value :
document{} << "someField" << "someValue" << finalize;
The collection.find_one() method takes a document::view, and document::values convert implicitly to document::views. Unfortunately, this means if you dynamically build a document in your call to find_one(), as above, you can shoot yourself in the foot:
collection.find_one(document{} << "someField" << "someValue" << finalize);
finalize makes a temporary document::value, then find_one converts that to a document::view. The temporary value is dropped on the floor, leaving your view value-less, like a dangling pointer.
A workaround is to make your value in a separate call, and keep it around:
document::value doc = document{} << "someField" << "someValue" << finalize;
collection.find_one(doc.view());
I suspect this is what's causing your queries to fail; if not, it's something to make your code resilient to nonetheless!
You can track this ticket for the real fix for this problem.

Qt Creator Sql Update Syntax Error

I am getting sql syntax errors for my update command in qt creator.
QSqlQuery q,q2;
for(int r=0; r<rowtablecount; r++){
q.prepare("update checkdata set "
"alobs=:alobs,"
"payee_name=:payee_name,"
"payee_nature=:payee_nature,"
"account_code=:account_code,"
"amount=:amount,"
"date_paid=:date_paid,"
"cancel_status=:cancel_status,"
"reviewer=:reviewer,"
"preparer=:preparer,"
"reciever=:reciever,"
"reviewer_pos=:reviewer_pos,"
"preparer_pos=:preparer_pos,"
"reciever_pos=:reciever_pos,"
"date_delivered=:date_delivered"
"where check_no = :checkno");
q.bindValue(":checkno", tabledata[r][2]);
qDebug() << tabledata[r][2];
q.bindValue(":alobs",tabledata[r][3]);
q.bindValue(":payee_name",tabledata[r][4]);
q.bindValue(":payee_nature",tabledata[r][5]);
q.bindValue(":account_code",tabledata[r][6]);
q.bindValue(":amount",tabledata[r][7].toDouble());
q.bindValue(":date_paid",tabledata[r][10]);
q.bindValue(":reviewer",reviewer);
q.bindValue(":preparer",preparer);
q.bindValue(":reciever",reciever);
q.bindValue(":reviewer_pos",reviewer_pos);
q.bindValue(":preparer_pos",preparer_pos);
q.bindValue(":reciever_pos",reciever_pos);
q.bindValue(":date_delivered",tabledata[r][9]);
q.bindValue(":acicn", acic_value);
q2.prepare("update acic set date_prepared=:date_prepared, total_amount=:total_amount where acic_num=:acic_num");
q2.bindValue(":date_prepared",tabledata[r][1]);
q2.bindValue(":total_amount",tabledata[r][8]);
q2.bindValue(":acic_num", acic_value);
if(!q.exec()){
if(q.lastError().isValid())
qDebug() << q.lastError().text() << " <error " << r;
QMessageBox::critical(this,tr("Error: Entry Failed"),tr("Data Field incorrect."));
if(!q2.exec()){
if(q2.lastError().isValid())
qDebug() << q2.lastError().text() << " <error " << r;
QMessageBox::critical(this,tr("Error: Entry Failed"),tr("Data Field incorrect."));
From the above, I get this error, repeated 3 times due to for loop:
"You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'check_no = '1248973'' at line 1 QMYSQL: Unable to execute query"
I suspect it is either the writing of the command in prepare, or perhaps reserved word, but I cannot find it.
Ideas on this would be most helpful.
It seems that I am a complete idiot for not seeing this. The error is in the line before "where check_no = :check_no". It just needs a space.
Thanks to Abhik Chakraborty for pointing it out.