Qt Creator Sql Update Syntax Error - c++

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.

Related

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.

How to correctly access xml attributes using pugixml?

I'm new to xml, and using the pugixml documentation I haven't been able to read a node attribute to the console. The core of the issue is that I don't understand how the node accessing structure works and I haven't been able to figure it out using my code.
The code provided is a lightly modified line from the actual pugixml manual, so I'm not sure why it isn't working.
XML FILE LOADED
<?xml version="1.0" encoding="utf-8"?>
<settings description="settings root description">
<!--settings for the options menu-->
<options description="game options">
<resolution description="resolution in 16:9 ratio">6</resolution>
<volume description="volume setting">0</volume>
</options>
</settings>
C++ CODE TRYING TO USE XML FILE
//set up and load settings xml doc
pugi::xml_document settingsXML;
pugi::xml_parse_result settingsResult = settingsXML.load_file("SFMLVania/include/Settings.xml");
std::cout << "Root description: " << settingsXML.root().attribute("description").as_string();
I'm expecting to see:
"Root description: settings root description"
in the console.
Instead, I'm getting:
"Root description: "
SECOND ATTEMPT -- to try and just get any data and find out where I am in the tree:
std::cout << "Second attempt: " << settingsXML.first_attribute().as_string();
All I got from the second attempt was the console spitting out: "Second attempt: "
It turns out, my load path didn't exist, I had forgotten to use ../ to go up a directory and out of the Debug folder where the .exe was stored. I figured this out by testing the load result that could be passed as a bool.
if (settingsResult)
{
std::cout << "returned true\n";
}
else
std::cout << "returned false\n";
if (!settingsResult)
{
std::cout << "also returned false\n";
}
I included some redundant returns in case the bool value didn't function as expected.
The result showed that there was no file loaded (it returned false), and when I reexamined my file structure and added the ../ as a test to the file path, it returned true.
For anyone that comes across this, you can prevent this error by adding a minimal parse check after the assigning of settingsResult like this:
pugi::xml_document settingsXML;
pugi::xml_parse_result settingsResult = settingsXML.load_file("SFMLVania/include/Settings.xml");
// Catch parsing error
if (!settingsResult )
{
std::cout << "ERROR: " << settingsResult.description() << '\n';
return -1;
}
This will catch a bad parse and log the error to the console.

Error:"Parameter count mismatch" in QSQLite [duplicate]

I am using quite a lot of parameterized queries in my code for performance reasons. In short, some of them work, some don't.
I initialize the query during construction of my database wrapper like this:
QString querystring = QString("SELECT somevalue FROM sometable "
"WHERE one_feature = :one_feature AND other_feature = :other_feature ");
myquery = QSqlQuery(db);
myquery.setForwardOnly(true);
myquery.prepare(querystring);
myquery is a QSqlQuery member variable of my database wrapper. Later on, in the function that wants to use this query, I do something like
int db_wrapper::fetch_some_value (int arg1, int arg2) {
myquery.clear();
myquery.bindValue(":one_feature", arg1);
myquery.bindValue(":other_feature", arg2);
qDebug() << "Bound values: " << myquery.boundValues();
bool OK = myquery.exec();
if (!OK) {
int number = myquery.lastError().number();
qDebug() << "db error " << number;
qDebug() << "db error " << myquery.lastError().text();
#ifdef USE_EXCEPTIONS
throw "Could not fetch some_value!";
#endif
}
// process data...
}
I always get the same error message/output:
Bound values: QMap((":one_feature", QVariant(int, 1) ) ( ":other_feature" , QVariant(int, 1) ) )
db error -1
db error " Parameter count mismatch"
terminate called after throwing an instance of 'char const*'
The exception is not surprising, but the parameter count mismatch is. The call to boundValues actually shows the right values and all, still I get this error message. I have similar queries that work just fine.
I tried substituting positional bind values, renamed the placeholders, used ? and positional bind values, all to no avail. Does anyone have an idea what the problem might be?
I use Qt 4.7.3 and SQLite 3.7.4-2
Usually this error means that the SELECT/UPDATE query itself is incorrect. You did not give the schema of the database so it's not possible to pinpoint which one. So one or more of somevalue, sometable, one_feature, or second_feature is not in the database/table.

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

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();
}