Syntax error in SQLite (C bindings) - c++

I got this error recently, and couldn't get rid of it. It's puzzling me, because the exact same request (copy-paste) works from the CLI like a charm.
I am using the C bindings, from a Qt application (I only discovered later that there was a Qt wrapper class for SQL databases).
The request in question is the following :
NSERT INTO classes(score,classe) VALUES((SELECT avg((julianday(arrivee)-julianday(debutCourse))/moyenne) FROM coureurs NATURAL JOIN resultats NATURAL JOIN courses NATURAL JOIN categories WHERE classe='4èmeB' AND moyenne IS NOT NULL),'4èmeB');
The error is :
near "'4èmeB'": syntax error
I have three tables I use there, which are classes, coureurs (runners), resultats (results), courses (races), categories.
For each class, I want to compute the following :
average of (runner's time/average time of its category).
Departure times are stored inside the courses (races) table, arrival times are stored inside the resultats (results) table and categories' average time are stored into categories.moyenne. If you have a more elegant way of performing such a request, I would be pleased to hear it. I would however like to have an explanation of what's going on here. Is this because of the UTF-8 characters ? It didn't seem to be a problem in other places.
In case it helps, here is the relevant C++ code :
void database::voidQuery(QString query)
{
sqlite3_stmt *res;
int rc =sqlite3_prepare_v2(db,query.toStdString().c_str(),query.length(),&res,NULL);
if(rc != SQLITE_OK){
fprintf(stderr, "Error in voidquery : %s in the request %s\n", sqlite3_errmsg(db),query.toStdString().c_str());
return;
}
sqlite3_step(res);
sqlite3_finalize(res);
}
Together with The calling code :
for (QStringList::iterator it = classes.begin();it != classes.end(); ++it)
{
QString query("INSERT INTO classes(score,classe) "
"VALUES(("
"SELECT avg((julianday(arrivee)-julianday(debutCourse))/moyenne) "
"FROM coureurs NATURAL JOIN resultats NATURAL JOIN courses NATURAL JOIN categories "
"WHERE classe='%1' and moyenne is not null),'%2');");
voidQuery(query.arg(*it).arg(*it));
}
classes is a QStringList containing the different rows of a precedent query.
Thanks in advance ! (I hope it's not a trivial problem; it took me quite some time to debug it).

Use
INSERT INTO classes (score,classe)
SELECT avg((julianday(arrivee)-julianday(debutCourse))/moyenne), '4èmeB'
FROM coureurs
NATURAL JOIN resultats
NATURAL JOIN courses
NATURAL JOIN categories
WHERE classe='4èmeB'
AND moyenne IS NOT NULL

Related

QSqlQuery is not binding values

I am performing queries against a MySQL database, and use code similar to below throughout my app. But for some reason the update below says 0 rows affected, when it should be 1. On digging deeper I discovered my bindValue commands don't seem to have any effect.
QSqlQuery* query = new QSqlQuery(m_db)
query->prepare(QString("UPDATE companies SET "
"NAME=:name, "
"ISUSER=:isuser, "
"ISVAR=:isvar, "
"ISOEM=:isoem, "
"CONTACT=:contact, "
"EMAIL=:email, "
"COMMENTS=:comments "
"WHERE ID=:id "
"LIMIT 1"));
query->bindValue(":name",rowData.name);
query->bindValue(":isuser",rowData.isEndUser);
query->bindValue(":isvar",rowData.isVAR);
query->bindValue(":isoem",rowData.isOEM);
query->bindValue(":contact",rowData.contact);
query->bindValue(":email",rowData.email);
query->bindValue(":comments",rowData.comments);
query->bindValue(":id",id);
bool queryOk = query->exec();
if (queryOk) {
qDebug() << query->executedQuery();
qDebug() << query->lastQuery();
qDebug() << query->lastError().text();
qDebug() << rowsAffected;
There must be something different/wrong in the code above causing the output below:
"UPDATE companies SET NAME=:name, ISUSER=:isuser, ISVAR=:isvar, ISOEM=:iSOEM, CONTACT=:contact, EMAIL=:email, COMMENTS=:comments WHERE ID=:id LIMIT 1"
"UPDATE companies SET NAME=:name, ISUSER=:isuser, ISVAR=:isvar, ISOEM=:iSOEM, CONTACT=:contact, EMAIL=:email, COMMENTS=:comments WHERE ID=:id LIMIT 1"
""
0
But I can't see the problem, and the query returns no errors. Yet the query string seems to contain the variable names not substituted.
QSqlQuery::executedQuery() won't show you the bound values, because the idea of bound values is that they never become part of the query itself (which completely eliminates the problem of escaping them). What you see is the actual query submitted to the database. The bound values are submitted to the database alongside the query string (very much same like with QSqlQuery).
As for the rowsAffected being zero, I don't see it being initialized or updated by the code in your example, which is likely why it says 0. you probably want to use query->numRowsAffected() instead.
Finally (not related to any of your questions), you don't need to allocate the QSqlQuery on heap (unless you really need the query to outlive the scope in which it is created) and you can simply allocate it on stack. Fewer dynamic allocations == fewer chances of memory leaks :-)

Adding nester OR statements in Doctrine 2, Querybuilder

I have a one to many entity:
User -> OrderPerson
A user can own multiple orderPersons.
An orderPerson is linked to Orders and can have multiple orders.
What I want to do is build a dynamic query to deal with this, this is what I have thus far:
public function getPaged($page, $count , $orderPersons = null)
{
$qb = $this->orderRepository->createQueryBuilder('c')
->orderBy('c.id', 'DESC');
if ($orderPersons != null )
{
foreach ($orderPersons AS $orderPerson)
{
$qb->where('c.orderPerson='.$orderPerson); ***
}
}
$query = $qb->getQuery();
}
Where I am struggling is how to write the line:
$qb->where('c.orderPerson='.$orderPerson);
I had a read of the documents and I think I need to use something like this but am not sure:
$qb->andWhere(
$qb->expr()->orX(
$qb->expr()->eq('c.orderPerson='.$orderPerson)
)
);
I am however unsure how to put this into a loop.
The one big criticism I have about the D2 documentation is that they spend a lot of time on exprs but most of the time you really don't need them. Just makes the code hard to read.
Having said that, you don't need OR conditions for your query, just an IN clause.
// Join the order persons
$qb->leftJoin(c.orderPersons,'orderPerson');
// Need at least one
if (is_array($orderPersons) && count($orderPersons)) {
$qb->andWhere('orderPerson.id IN (:orderPersons));
$qb->setParameter('orderPersons',$orderPersons);
}
Untested of course so there may be a syntax error but you should get the idea.

Insert JSON format in Mysql query using C++

I am using JSON format to save data in my c++ program , i want to send it to MySql database (the table tab has one column with type : TEXT) but the query failed (tested also VARCHAR and CHAR )
this is a part of the code since we are not interrested in the rest
string json_example = "{\"array\":[\"item1\",\"item2\"], \"not an array\": \"asdf\"}";
mysql_init(&mysql); //initialize database connection
string player="INSERT INTO tab values (\"";
player+= json_example;
player += "\")";
connection = mysql_real_connect(&mysql,HOST,USER,PASSWD,DB,0,NULL,0);
// save data to database
query_state=mysql_query(connection, player.c_str()); // use player.c_str()
to show the final query that will be used : cout << player gives :
INSERT INTO tab values ("{"array":["item1","item2"], "not an
array": "asdf"}")
using for example string json_example = "some text"; is working
but with the json format it is not working , maybe the problem came from the use of curly bracket {} or double quotes "" but i haven't find a way to solve it .
i'm using :
mysql Ver 14.14 Distrib 5.5.44, for debian-linux-gnu (armv7l) under raspberry pi 2
Any help will be appreciated , thanks .
Use a prepared statement. See prepared statements documentation in the MySQL reference manual.
Prepared statements are more correct, safer, possibly faster, and keep your code cleaner. You get all those benefits and don't need to escape anything. There is hardly a reason not to use them.
Something like this might work. But take it with a grain of salt, because I have not tested or compiled it. It should just give you the general idea:
MYSQL_STMT* const statement = mysql_stmt_init(&mysql);
std::string const query = "INSERT INTO tab values(?)";
mysql_stmt_prepare(statement, query, query.size());
MYSQL_BIND bind[1] = {};
bind[0].buffer_type = MYSQL_TYPE_STRING;
bind[0].buffer = json_example.c_str();
bind[0].buffer_length = json_example.size();
mysql_stmt_bind_param(statement, bind);
mysql_stmt_execute(statement);

referencing data within the groups of a list in F#

I performed my first query with a grouping function using the following code:
let dc = new TypedDataContext()
open MathNet.Numerics.Statistics
let newData = query { for x in dc.MyData do
where (x.ID = "number of type string")
groupBy x.Code into g
let average = query { for x in g do
averageBy x.Billed_Amt }
select (g, average) }
|> Seq.toList
System.Console.WriteLine(newData)
I am now wanting to calculate the standard deviation of the billed amounts in each group. However, when I try to reference the column, 'Billed_Amt,' like so
let sd = newData.Billed_Amt.StandardDeviation()
I receive the following error: "constructor or member 'Billed_Amt' is not defined."
I also tried newData.g.Billed_Amt.StandardDeviation(), in case I needed to reference the groups first, but I got the same error message referring to 'g'.
How do I overcome this?
I will say that I notice that the 'list' I created with the query claims to have 63 items. These would be the different group keys, not the rows of data themselves.
I feel like the research I have done online to solve this problem has just sent me in circles. Most of the resources online do not dumb it down enough for newbies like me. Any help would be appreciated.
Thank you!

Getting odd behavior from $query->setMaxResults()

When I call setMaxResults on a query, it seems to want to treat the max number as "2", no matter what it's actual value is.
function findMostRecentByOwnerUser(\Entities\User $user, $limit)
{
echo "2: $limit<br>";
$query = $this->getEntityManager()->createQuery('
SELECT t
FROM Entities\Thread t
JOIN t.messages m
JOIN t.group g
WHERE
g.ownerUser = :owner_user
ORDER BY m.timestamp DESC
');
$query->setParameter("owner_user", $user);
$query->setMaxResults(4);
echo $query->getSQL()."<br>";
$results = $query->getResult();
echo "3: ".count($results);
return $results;
}
When I comment out the setMaxResults line, I get 6 results. When I leave it in, I get the 2 most recent results. When I run the generated SQL code in phpMyAdmin, I get the 4 most recent results. The generated SQL, for reference, is:
SELECT <lots of columns, all from t0_>
FROM Thread t0_
INNER JOIN Message m1_ ON t0_.id = m1_.thread_id
INNER JOIN Groups g2_ ON t0_.group_id = g2_.id
WHERE g2_.ownerUser_id = ?
ORDER BY m1_.timestamp DESC
LIMIT 4
Edit:
While reading the DQL "Limit" documentation, I came across the following:
If your query contains a fetch-joined collection specifying the result limit methods are not working as you would expect. Set Max Results restricts the number of database result rows, however in the case of fetch-joined collections one root entity might appear in many rows, effectively hydrating less than the specified number of results.
I'm pretty sure that I'm not doing a fetch-joined collection. I'm under the impression that a fetch-joined collection is where I do something like SELECT t, m FROM Threads JOIN t.messages. Am I incorrect in my understanding of this?
An update : With Doctrine 2.2+ you can use the Paginator http://docs.doctrine-project.org/en/latest/tutorials/pagination.html
Using ->groupBy('your_entity.id') seem to solve the issue!
I solved the same issue by only fetching contents of the master table and having all joined tables fetched as fetch="EAGER" which is defined in the Entity (described here http://www.doctrine-project.org/docs/orm/2.1/en/reference/annotations-reference.html?highlight=eager#manytoone).
class VehicleRepository extends EntityRepository
{
/**
* #var integer
*/
protected $pageSize = 10;
public function page($number = 1)
{
return $this->_em->createQuery('SELECT v FROM Entities\VehicleManagement\Vehicles v')
->setMaxResults(100)
->setFirstResult($number - 1)
->getResult();
}
}
In my example repo you can see I only fetched the vehicle table to get the correct result amount. But all properties (like make, model, category) are fetched immediately.
(I also iterated over the Entity-contents because I needed the Entity represented as an array, but that shouldn't matter afaik.)
Here's an excerpt from my entity:
class Vehicles
{
...
/**
* #ManyToOne(targetEntity="Makes", fetch="EAGER")
* #var Makes
*/
public $make;
...
}
Its important that you map every Entity correctly otherwise it won't work.