Save two things at the same time - Node Js - mysql

I am currently developing a system where I store custumer's information... One of these information is the custumer's address. To do so, I create two tables in my database: Address and Custumer.
I use the address stored in the custumer table as a foreign key... so far so good. The problem is that I need to first save the address and after get the result id (The id is auto increment) and create the query to save the custumer using that id, but I need to do that at the same function using node, unfortunelly, as I try to do so, I get this error:
'Error: Cannot enqueue Query after invoking quit.'
Below is my code:
this.save = function(connection, object, callback){
let sqlAdress = utilClient.createSaveAdressQuery(object.address);
connection.query(sqlAdress , (error, results) => {
if(error) throw error;
objeto.address.id = results.insertId;
//After that the address is saved, I try to save the client
let sql = utilCliente.createSaveQuery(object);
connection.query(sql, (callback));
})
}
Does anyone know how to help me out? Thanks in advance!
This my callback code:
app.post("/save", function(request, response){
var custumer = request.body;
var connection = dbConnection();
eventoBanco.salvar(connection, custumer, function(error, result){
response.send(result);
if(error != null) console.log(error);
});
connection.end();
});

I think I was able to solve that problem by doing so :
clienteFactoryDAO.alterar(connection, cliente, function(erro, result){
response.send(result);
if(erro != null) console.log(erro);
connection.end();
});
As you can notice now, I close the connection query in the callback passed into the function. MY MISTAKE WAS as the #Himanshusharma nicely pointed: I was closing the connection outside the callback function, and as you know, JavaScript is asynchronous, so it was closing the connection too soon and when I needed one, I got nothing. Thanks in advance and I hope it helps someone at some point

Related

Updating record in MySQL using node.js and rest approach

Short task description: I need to update the record in MySQL DB using the Node.js by the id of this record. The data for update are sent in JSON format using RESTEASY. I wrote the following code:
app.put('/:enablerId', function(req, res){
var jsondata = req.body;
var enablerid = req.params.enablerId;
connection.query("UPDATE enablers SET ? WHERE id=?", [jsondata, enablerid], function(error, results){
if(error) {
console.log('Query error');
} else {
console.log('Updated ' + results.affectedRows + ' row ');
}
});
});
Response, that I get 0 rows are affected, in fact, nothing has been updated.
I've got an impression, that problem should be somehow connected to proper url attribute
app.put('/:enablerId', function(req, res)
If so, general question how to get the id from url? However, I am not sure. I am a bit lost, will be grateful for any help.
Thank you in advance.

Return data from database.query() using sailsjs

I am trying to build an api using sailsjs that calls stored procedures of a MYSQL database. I decided to decouple the query by adding it to a service so that others functions might be able to call them and use them. Below is what I came up with.
under /api/controller/MySqlController
getAllUsers: function (req, res) {
MySqlSpService.spGetAllUsers(function(err, result){
if(err) return res.serverError(err);
return res.ok(result[1]);
});
},
under /api/services/MYSQLService
var MySqlSpService= {
spGetAllUsers: function(callback) {
Database.query('call userDb.sp_get_all_users(#message, #mystatus)', function (err, results) {
callback(err, results);
}); // end query
}
module.exports = MySqlSpService;
When I hit the api the data is displayed exactly how I thought it would be. But the problem is that when I try to call the spGetAllUsers service and assign to a variable, I get a undefined value.
Like this:
var users = MySqlSpService.spGetAllUsers(function(err, result){
if(err) return res.serverError(err);
return result[1];
});
I believe the problem is with the callbacks but I am not sure how to retrieve the data from the query. I have searched for an answer but I can't seem to find the right search terms that match my problem. Any help would be greatly appreciated Thanks in advance.
Indeed, your problem is about callback and asynchronous code.
The MySqlSpService.spGetAllUsers() function does not return anything, there is no return statement in this method. But it executes a callback function where you have the opportunity to execute code that depends on the SQL query result.
You have to write your code like this because the database query is executed asynchronously.
console.log('This is executed first');
MySqlSpService.spGetAllUsers(function(err, result){
console.log('This is executed when the result of the database query is received');
if(err) return res.serverError(err);
users = result[1];
/**
* Here you can access to the "users" data
* and execute code depending on it
*/
});
console.log('This is executed in second and it is not possible to know the result of the query yet');
Tools like async can help you to organize your asynchronous code. By default, async is available globally in sails.js.

Return error response in nodejs

Evening stack! Tonight I decided to play around with some NodeJS and I'm having a little trouble understanding the appropriate way for me to handle errors in this situation.
I have a table that simply stores playerName and the name must be unique. So rather than just try to insert and get an error, I want to first make a select and if I get a result, return a 400 to the user and let them know the name already exists. If not, continue on as normal, insert the name, and return a 203.
What I've got clearly isn't working. I've attempted a try/catch and that didn't work. And I clearly can't return an error with the methods I'm using. So what's a good way to go about this?
router.post('/addPlayer' , function(req, res, next){
var playerName = req.body.name;
if(playerName === undefined || playerName.length === 0)
{
return res.status(400).send('No name provided');
}
var query = 'SELECT name FROM players WHERE name LIKE ?';
var inserts = [playerName];
query = connection.format(query , inserts);
connection.query(query, function(err, results){
if(err) return res.status(500).send('Error connecting to database.');
if(results.length !== 0) return res.status(400).send('This name has already been used.');
});
query = 'INSERT INTO players (name) VALUES(?)';
inserts = [playerName];
query = connection.format(query , inserts);
connection.query(query, function(err){
if(err) return res.status(500).send('Error connecting to database.');
});
res.status(201).send("Added player: " + playerName);
});
In this current version my obvious problem is Node crashes complaining about not being able to set the headers after they've already been sent. I know what I need to do. Which is end the execution of the route and return the error to the browser, but I'm just not clear on how to best go about that.
I'm using the Express framework and mysql.
Thanks.
The problem is you're running both queries in parallel. So the INSERT is executed before the response of the SELECT is received. Which means that there is a race condition. Both queries tries to send res.status() but one will happen after the other which causes the error.
To fix this, wait until the SELECT is received then do your INSERT:
var query = 'SELECT name FROM players WHERE name LIKE ?';
var inserts = [playerName];
query = connection.format(query , inserts);
connection.query(query, function(err, results){
if(err) return res.status(500).send('Error connecting to database.');
if(results.length !== 0) return res.status(400).send('This name has already been used.');
query = 'INSERT INTO players (name) VALUES(?)';
inserts = [playerName];
query = connection.format(query , inserts);
connection.query(query, function(err){
if(err) return res.status(500).send('Error connecting to database.');
res.status(201).send("Added player: " + playerName);
});
});
Is there anything wrong with sending the error(err) itself? For example:
if (err)
res.send(err);

Node Mysql Cannot Enqueue a query after calling quit

where do i close the mysql connection?
I need to run queries in sequence. I am writing code that looks like this at present:
var sqlFindMobile = "select * from user_mobiles where mobile=?";
var sqlNewUser = "insert into users (password) values (?)";
//var sqlUserId = "select last_insert_id() as user_id";
var sqlNewMobile = "insert into user_mobiles (user_id, mobile) values (?,?)";
connection.connect(function(err){});
var query = connection.query(sqlFindMobile, [req.body.mobile], function(err, results) {
if(err) throw err;
console.log("mobile query");
if(results.length==0) {
var query = connection.query(sqlNewUser, [req.body.password], function(err, results) {
if(err) throw err;
console.log("added user");
var user_id = results.insertId;
var query = connection.query(sqlNewMobile, [user_id, req.body.mobile], function(err, results) {
if(err) throw err;
console.log("added mobile");
//connection.end();
});
});
}
});
//connection.end();
(I am a beginner with node, npm-express and npm-mysql. I have tried searching SO for "express mysql cannot enqueue" to find related questions and have not found them.)
I fixed this problem use this method:
connection.end() in your connection.query function
The fixed code is here
If you're using the node-mysql module by felixge then you can call connection.end() at any point after you've made all of the connection.query() calls, since it will wait for all of the queries to finish before it terminates the connection.
See the example here for more information.
If you're wanting to run lots of queries in series, you should look into the async module, it's great for dealing with a series of asynchronous functions (i.e. those that have a callback).
Maybe the problem is that the mySQL query is executed after the connection is already closed, due to the asynchronous nature of Node. Try using this code to call connection.end() right before the thread exits:
function exitHandler(options, err) {
connection.end();
if (options.cleanup)
console.log('clean');
if (err)
console.log(err.stack);
if (options.exit)
process.exit();
}
//do something when app is closing
process.on('exit', exitHandler.bind(null, {cleanup: true}));
Code adapted from #Emil Condrea, doing a cleanup action just before node.js exits
In my case connection.end was being called in a spot that was hard to notice, so an errant call to connection.end could be the problem with this error

NodeJS mysql query returns empty result

i'm new to NodeJS (duh!).
I know it executes functions asynchronous but I still cannot see what causes this phenomenon:
I am using the express and mysql modules and trying to execute an SQL query based on request parameters. It is supposed to be a simple validation API feature where the server is going to lookup a user in a database by listening on a specific URL for two request parameters (user and passwd).
The problem is that the SQL query always returns an empty object as result when I do this using the request parameters in the query.
However, if i hard code the query and run it outside the app.get(...) I get the desired result! But I need this to work on demand by request...
(I'm not intending to use GET-request later on, this example is for debugging purposes :))
What am i doing wrong here?
Here's my code:
// Server and Mysql setup here
var app = require('express').createServer(),
SERVER_PORT = 8080;
var Client = require('mysql').Client,
client = new Client(),
...
// User, password and database setup here, cropped out from this example //
// ...
function validateUser(user, passwd, callback) {
client.query('SELECT date FROM '+CUSTOMERS_TABLE+' WHERE email="'+user+'" AND passwd="'+passwd+'";',
function selectCb(err, results, fields) {
if (err) {
throw err;
}
console.log(fields);
callback(results);
});
}
app.get('/', function(req, res){
var url_parts = url.parse(req.url, true);
var query = url_parts.query;
if((typeof query[REQ_PARAM_USER] != 'undefined' && typeof query[REQ_PARAM_PASSWD] != 'undefined')
&& (query[REQ_PARAM_USER] != '' && query[REQ_PARAM_PASSWD] != '')) {
validateUser(REQ_PARAM_USER, REQ_PARAM_PASSWD, function(results) {
console.log(results);
});
}
res.end("End")
});
app.listen(SERVER_PORT);
console.log('Server running at port '+SERVER_PORT);
Oh, and by the way, console.log(fields) outputs the correct fields! But why not the results?
You are passing the wrong parameters to validateUser:
validateUser(REQ_PARAM_USER, REQ_PARAM_PASSWD, // ...
What you really want:
validateUser(query[REQ_PARAM_USER], query[REQ_PARAM_PASSWD], // ...
Edit: A few other issues with your code:
You don't have to parse the url. Express does this for you, and the query is available as req.query.
You shouldn't throw in asynchronous code. It will give unexpected results. Instead, stick to the nodejs paradigm of passing (err, results) to all callbacks, and do proper error checking where you can -- i.e., in your verifyUser, pass along the error with the callback and check for errors in your get handler. Either res.send(500) (or something) when you get an error, or pass it along to the express error handler by calling next(err).
validateUser(query[REQ_PARAM_USER], query[REQ_PARAM_PASSWD], function(err, results) {
if(err) {
console.error(err);
res.send(500);
} else {
console.log(results);
res.send(results);
}
});
Never pass query parameters directly to something like an SQL query. Instead, use parameters for your SQL query:
client.query('SELECT date FROM '+CUSTOMERS_TABLE+' WHERE email=? AND passwd=?', [user, passwd], // ...