Nodejs MySQL ER_PARSE_ERROR on VALID query - mysql

I've tried using mysql lib with nodejs and a simple query like SELECT * FROM table; works, but now that I've tried to construct a real query to update my database it doesn't work.
I have used an online validating tool and it checks out.
var mysql = require('mysql');
var request = require('request');
request.get('http://localhost:8080/dump/asda.dump', function (error, response, body) {
if (!error && response.statusCode == 200) {
var data =JSON.parse(body);
var products = data['products'][0];
var myquery = "INSERT INTO `products2` (";
var midquery = ") VALUES (";
for (var k in products) {
if (typeof products[k] === 'number') var v = products[k];
else if (typeof products[k] === 'string') var v = "\'" + products[k]+ "\'";
else if (typeof products[k] === 'boolean') var v = products[k];
else continue;
myquery = myquery + "`" + k + "`,";
midquery = midquery + v + ",";
}
myquery = myquery.slice(0,-1);
midquery = midquery.slice(0, -1);
print(myquery + midquery + ")");
connection.connect();
connection.query(myquery, function (err, rows, fields) {
if (!err) console.log(rows);
else console.log(err);
});
connection.end();
}
});
I have tried both the version with the ticks and without the ticks an none of them work.
Possible reasons might be
Too long query. Maybe some internal char limit exeeded?
Unsupporded characters. I am pretty sure I have quite a few Croatian ćčćš in there. How to I support that?
Improper ' " escaping (although it seems ok to me).
I have 'code' as a table column. I've checked and it's not a reserved keyword in mysql but it's blued in MySQL Workbench so maybe it breaks things somehow.
What I get is:
{ [Error: ER_PARSE_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 '' at line 1]
code: 'ER_PARSE_ERROR',
errno: 1064,
sqlState: '42000',
index: 0 }

You should try with the ticks whenever you are using the database entities inside the query like the table names or database variables. As far as your query is concerned, only myquery is getting into the function as your database statement and it doesn't contain the whole query. As a result you are getting an error because of your incomplete complete query and improper syntax in it(as it is incomplete already). Your print statement will print it right because of the concatenation that you have used. If you are able to keep the concatenated query string in a variable such as:
var new_query=myquery + midquery + ")";
And then using it as
connection.query(new_query, function (err, rows, fields) {
if (!err) console.log(rows);
else console.log(err);
});
I think your query should work. Thank you...!

Related

multiple dependent mysql queries in nodejs...promise not the answer?

I have recently learned how to execute promises in order to run three mysql requests synchronously. I'm disappointed, because I'm learning this is not the solution if I want to run the dependent mysql requests in order. For example, the first gets a variable, which is needed for the second:
My nodejs code:
data.used_time = 7;
var sql;
var sesh_save_val;
var mysql = require('mysql');
//Delete whiteboard session
var con = mysql.createPool({
connectionLimit: 15,
host: "xxxx",
user: "xx",
password: "xxxx",
database: "xxxx"
});
var current_min;
new Promise ((resolve,reject) => {
sql = `SELECT minutes FROM Students WHERE sesh_save = (?)`;
con.query(sql, id, function (err, result)
{
if (err) throw err;
current_min = result[0].minutes;
console.log("no error thrown I think..");
console.log("current_min: " + current_min);
});
resolve("did first func");
}).then((val)=> {
console.log(val);
sql = 'UPDATE Students SET minutes = (?) WHERE sesh_save = (?)';
var min_left = current_min - data.used_time;
console.log("used time: " + data.used_time + " ");
console.log("min_left: " + min_left + " " + "id: " + id);
con.query(sql,[min_left, id], function (err, result)
{
if (err) {console.log(err);}
});
return "did second func";
});
The output is only partially what I would expect. It is:
"did first func", "used_time: 0", min_left: NaN, id: whiteboard-xxxxx-xxxx
"did second func"
"current_min: 4299"
And then error on the line with "con.query(sql,[min_left, id], function (err, result)" because min_left did not exist. Why did min_left not exist? Output showed that current_min existed. However, it existed AFTER the first mysql query resolved, which took so long, that we were able to get into the second .then statement while it's still taking it's time with the first sql query, and the second dependent mysql statement wasn't able to process correctly. How do I fix this?
Thanks for any remarks.
You don't really need 2 queries. You will be good to go with:
sql = 'UPDATE Students SET minutes = minutes - (?) WHERE sesh_save = (?)';
con.query(sql,[data.used_time, id], function (err, result)...

Node function inputting undefined variables into SQL database

I'm sure this is a simple error in my syntax but I'm currently using a nodejs function to input into my SQL database, however, while the overall query works, and some variables get input correctly, a couple are input as undefined, which has thrown me for a loop. I'll input the query below and I presume I either added extra punctuation where not required or something.
con.query("INSERT INTO _rounds(roundnum, roundse, roundtk, winner) VALUES('"+ roundnumres +"', '"+ roundse +"', '"+ roundtk +"', '"+ roundwinner +"')", function (err, result) {
});
For more information, the roundnumres and the roundtk variables are the ones inserted as undefined, and are both defined by a random string generator which looks as follows:
function makese(length) {
var roundse = '';
var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var charactersLength = characters.length;
for ( var d = 0; d < length; d++ ) {
roundse += characters.charAt(Math.floor(Math.random() * charactersLength));
}
return roundse;
}
var roundse = makese(20);
Any help would be appreciated!
you could do this. you don't have to concat strings using plus
const query = `INSERT INTO _rounds(roundnum, roundse, roundtk, winner) VALUES('${roundnumres}', '${roundse}, '${roundtk}', '${roundwinner}')"
con.query(query, () => {})

Escaping Node.JS MySQL Issues

Im creating a daemon that automatically changes MYSQL table contents randomly around my pages. (wordpress tables)
I have a array of stories that the system will read and then UPDATE the mysql in the tables, and as well update the timestamp on the server.
My code looks like this
//required libraries
fs = require('fs')
var mysql = require('mysql');
var dateFormat = require('dateformat');
var now = new Date();
//mysql table
var connection = mysql.createConnection({
host : 'yomamabinshoppin',
user : 'nonya',
password : 'defineltynonya',
database : 'okbye'
});
connection.connect();
//sitelisting
var sites = [ 'wp_counlwarehouseposts', 'wp_infounlwarehouseposts', 'wp_infowarehouse31posts', 'wp_netunlwarehouseposts', 'wp_netwarehouse31posts', 'wp_orgunlwarehouseposts', 'wp_orgwarehouse31posts', 'wp_stagcomwarehouseposts', 'wp_stagcowarehouseposts', 'wp_staginfwarehouseposts', 'wp_stagnetwarehouseposts', 'wp_stagorgwarehouseposts'];
//select story from catalogue
function ss (id,callback){
fs.readFile('./' + id +'.txt', 'utf8', function (err,data) {
callback(data);
});}
sites.forEach(function(entry) {
ss(Math.floor(Math.random() * 12), function (returnvalue){
fs.writeFile(entry, returnvalue);
connection.query("UPDATE `warehous_wordpress`.`"+entry+"` SET `post_date` = '"+ dateFormat(now, "yyyy-m-d") +" 01:00:01' WHERE `"+entry+"`.`ID` =1", function(err, rows, fields) {
if (err) throw err;
});
fs.appendFile('postlog.log', "UPDATE `warehous_wordpress`.`"+entry+"` SET `post_content` = '"+returnvalue+"' WHERE `"+entry+"`.`ID` = 1" , function (err) {
});
connection.query("UPDATE `warehous_wordpress`.`"+entry+"` SET `post_content` = '"+returnvalue+"' WHERE `"+entry+"`.`ID` = 1", function(err, rows, fields) {
if (err) throw err;
});
});
});
The issue in question here is at the line of
fs.appendFile('postlog.log', "UPDATE `warehous_wordpress`.`"+entry+"` SET `post_content` = '"+returnvalue+"' WHERE `"+entry+"`.`ID` = 1" , function (err) {
});
Where returnvalue is my story, and where entry is the current table name.
Error: ER_PARSE_ERROR: You have an error in your SQL syntax; check the manual th
at corresponds to your MySQL server version for the right syntax to use near 're
frightened can become a safety issue. When designing something to scare visit'
at line 1
The story that it is referring to has the text of this.
SCARE PEOPLE THE RIGHT WAY.
"We always try to scare forward to try to keep the flow going," Travis says. "A lot of times we try to scare further down the path rather than being scared into the wall," which slows the circulation of traffic through the maze.
Plus, where people instinctively move when they're frightened can become a safety issue. When designing something to scare visitors, you have to think about how people will react—and what they might jump into if they leaped backward in terror. "You never really know how bad something is going to scare somebody," Travis explains. "We try to keep the opposite wall clear from any kind of metal props or anything like that."
At first i thought the issue was related to some html in my stories, so i removed ALL of the html in the stories, same issue was happening.
Any advice to how i could fix this?
Thank you.
UPDATE 1
After escaping the variables for the Query, the modified code, still the same parsing issue on the SQL end
//required libraries
fs = require('fs')
var mysql = require('mysql');
var dateFormat = require('dateformat');
var now = new Date();
//mysql table
var connection = mysql.createConnection({
...
});
connection.connect();
//sitelisting
var sites = [ 'wp_counlwarehouseposts', 'wp_infounlwarehouseposts', 'wp_infowarehouse31posts', 'wp_netunlwarehouseposts', 'wp_netwarehouse31posts', 'wp_orgunlwarehouseposts', 'wp_orgwarehouse31posts', 'wp_stagcomwarehouseposts', 'wp_stagcowarehouseposts', 'wp_staginfwarehouseposts', 'wp_stagnetwarehouseposts', 'wp_stagorgwarehouseposts'];
//select story from catalogue
function ss (id,callback){
fs.readFile('./' + id +'.txt', 'utf8', function (err,data) {
callback(data);
});}
sites.forEach(function(entry) {
ss(Math.floor(Math.random() * 12), function (returnvalue){
fs.writeFile(entry, returnvalue);
connection.query("UPDATE `warehous_wordpress`.`"+entry+"` SET `post_date` = '"+ dateFormat(now, "yyyy-m-d") +" 01:00:01' WHERE `"+entry+"`.`ID` =1", function(err, rows, fields) {
if (err) throw err;
});
fs.appendFile('postlog.log', "UPDATE `warehous_wordpress`.`"+ entry + "` SET `post_content` = '"+ mysql.escape(returnvalue) +"' WHERE `"+ entry +"`.`ID` = 1" , function (err) {
});
connection.query("UPDATE `warehous_wordpress`.`"+ entry +"` SET `post_content` = '" + mysql.escape(returnvalue) + "' WHERE `"+ entry +"`.`ID` = 1", function(err, rows, fields) {
if (err) throw err;
});
});
});
You need to always escape your variables correctly.
If your returnvalue is they're then this portion of your query:
SET `post_content` = '" + returnvalue + "' WHERE
will become:
SET `post_content` = 'they're' WHERE
As you can see, this will result into a syntax error at 're
In the worst case this can be used to inject some data into your database. If returnvalue e.g. would be they', ID='1, then your query will be:
SET `post_content` = 'they', ID='1' WHERE
So you always have to escape you values, either using ? or mysql.escape
Using ?? and ?:
connection.query(
"UPDATE `warehous_wordpress`.?? SET `post_content` = ? WHERE ??.`ID` = 1",
[entry, returnvalue, entry] ,
function(err, rows, fields) {});
Using mysql.escapeId and mysql.escape:
connection.query(
"UPDATE `warehous_wordpress`." + mysql.escapeId(entry) +
" SET `post_content` = " + mysql.escape(returnvalue) +
" WHERE " + mysql.escapeId(entry) + ".`ID` = 1",
function(err, rows, fields) {});
I would suggest you to use ? and ??.
Try like below
fs = require('fs');
var mysql = require('mysql');
var dateFormat = require('dateformat');
var async = require('async');
var connection = mysql.createConnection({
...
});
connection.connect();
var sites = [ 'wp_counlwarehouseposts', 'wp_infounlwarehouseposts', ...];
function copyFile(source, target, callback) {
var rs = fs.createReadStream(source);
rs.on('error', callback);
var ws = fs.createWriteStream(target);
ws.on('error', callback);
ws.on('close', callback);
rs.pipe(wr);
}
function updateSite(site, callback) {
copyFile('./' + Math.floor(Math.random() * 12) +'.txt', site, function(err) {
if (err)
return callback(err);
connection.query(
'UPDATE warehous_wordpress.? SET post_date = ? WHERE ?.ID=1',
[site, dateFormat(now, 'yyyy-m-d') + ' 01:00:01', site],
callback
);
});
}
async.eachSeries(sites, updateSite, function (err) { if (err) throw err; });

Node.js MySQL query error ER_PARSE_ERROR

I have a problem with a MySQL query inside of a NodeJS application. In my snippet I loop through a triple-nested for cycle and save some different data in the post variable. What I want to do is checking whether this data already exists into the database and, if not, execute an INSERT query.
Been trying in any possible way, however I get the following error:
Error: ER_PARSE_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 ' `user_id` = '421', `product_id` = '1', `brick_id` = '1', `effect_date` = '2016-' at line 1
I don't think there are any SQL errors, I have been checking a thousand of times but maybe I am missing something. This is what I tried to do:
router.post('/relations/finalize', function (req, res, next) {
// Executing a cycle for every possible data combination
for (var i = 0; i < req.body.users_selection.length; i++) {
for (var j = 0; j < req.body.products_selection.length; j++) {
for (var k = 0; k < req.body.bricks_selection.length; k++) {
post = {
owner_id: req.session.userid,
user_id: req.body.users_selection[i],
product_id: req.body.products_selection[j],
brick_id: req.body.bricks_selection[k],
effect_date: req.body.year + "-" + req.body.month + "-01 00:00:00",
}
// Checking if the entry already exists
req.app.locals.connection.query({
sql: 'SELECT * FROM relations WHERE user_id = ? AND product_id = ? AND brick_id = ? AND effect_date >= ?',
timeout: 40000, // 40s
values: [post]
}, function (err, rows, fields) {
if (err) throw err;
else {
if (rows.length > 0) {
console.log("The entry already esists");
} else {
req.app.locals.connection.query("INSERT INTO relations SET ?", post, function (err, row, fields) {
if (err) throw err;
else {
console.log("The entry didn't exists and was then created.");
//res.redirect("/relations/wizard");
}
});
}
}
});
}
}
}
});
Any help will be greatly appreciated to solve this issue.
EDIT: I also tried to pass separate values into the SELECT query, like this:
values: req.body.users_selection[i], req.body.products_selection[j], req.body.bricks_selection[k], req.body.year + "-" + req.body.month + "-01 00:00:00"
But the result I get is that the INSERT query is called X times with the same values, as the for loops are not going through, maybe because of the asynchronous nature of Node..

How to pass parameters to mysql query callback in nodejs

I'm trying to figure out the correct way of passing custom data to a query call to be made available in the callback.
I'm using MySQL library in nodejs (all latest versions).
I have a call to connection.query(sql, function(err, result) {...});
I couldn't find a way to 1) pass custom data/parameter to the call so that 2) it can be made available when the callback is invoked.
So what is the proper way of doing so?
I have the following (pseudo-code):
...
for (ix in SomeJSONArray) {
sql = "SELECT (1) FROM someTable WHERE someColumn = " + SomeJSONArray[ix].id;
connection.query(sql, function (err, result) {
...
var y = SomeJSONArray[ix].id;
};
}
From the code above, I need to be able to pass the current value of "ix" used in the query to the callback itself.
How do I do that?
If you are using node-mysql, do it like the docs say:
connection.query(
'SELECT * FROM table WHERE id=? LIMIT ?, 5',[ user_id, start ],
function (err, results) {
}
);
The docs also have code for proper escaping of strings, but using the array in the query call automatically does the escaping for you.
https://github.com/felixge/node-mysql
To answer the initial question with a complete answer/example to illustrate, wrap the callback with an anonymous function which immediately creates a scope containing a "snapshot" if you will of the data passed in.
var ix=1;
connection.query('SELECT 1',
(function(ix){
return function(err, rows, fields) {
console.log("ix="+ix);
console.log(rows);
};
})(ix));
For those new to this concept as I was 20 minutes ago, the last })(ix)); is the outer var ix=1 value which is passed into (function(ix){. This could be renamed (function(abc){ if you changed the console.log("ix="+abc);
fwiw (Thanks Chris for the link which filled in the blanks to arrive at a solution)
While it is OK to pass variables or objects to a mysql query callback function using the tactic described earlier -- wrapping the callback function in an anonymous function -- I think it is largely unnecessary, and I'll explain why with an example:
// This actually works as expected!
function run_query (sql, y) {
var y1 = 1;
connection.query (sql, function (error, rows, fields) {
if (! error)
{
var r = rows[0];
console.log ("r = " + r[1]);
console.log ("x = " + x);
console.log ("y = " + y);
console.log ("y1= " + y);
console.log ("");
}
else
{
console.log ("error = " + error);
}
});
};
var x = 5;
console.log ("step 1: x = " + x);
run_query ("SELECT 1", x);
x = x + 1;
console.log ("step 2: x = " + x);
run_query ("SELECT 1", x);
x = x + 1;
console.log ("step 3: x = " + x);
Produces the following output:
step 1: x = 5
step 2: x = 6
step 3: x = 7
r = 1
x = 7
y = 5
y1= 5
r = 1
x = 7
y = 6
y1= 6
The fear is that the second call to run_query() will overwrite the variable y and/or y1 before the first call to run_query() has a chance to invoke its callback function. However, the variables in each instance of the called run_query() function are actually isolated from each other, saving the day.
MySQL con.query has overloaded function. Inside of callback you use global variable or any variable that is passed into your function parameter. For example:
Example 1: it takes sql string and callback function
var adr = 'Mountain 21';
var sql = 'SELECT * FROM customers;
con.query(sql, function (err, result) {
if (err) throw err;
console.log(adr);
});
Example 2: it takes sql string, parameter and callback function
var adr = 'Mountain 21';
var sql = 'SELECT * FROM customers WHERE address = ?';
con.query(sql, [adr], function (err, result) {
if (err) throw err;
console.log(adr);
});