Render multiple queries in Node Express - mysql

I am working with Node.js (express) and MySQL and I have had problems trying to make several queries in the same route. The error it throws is:
Can't set headers after they are sent.
And my code is this:
router.post('/test', function (req, res, next){
db.query("select COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS where
TABLE_NAME = 'registros';", function (error, results, fields) {
if (error) throw error;
res.render('test', {
columnNames: results
});});
db.query("SELECT * FROM registros", function (error, resp, fields) {
if (error) throw error;
res.render('test', {
dataRegistros: resp
});});
});
I understand that it may be because it is rendering twice in the same route. What would be the correct method to make several SQL queries and return them to a file in view?
Regards!

According to mysql nodejs driver you can setup it o combine the queries and return an array with results
You must set this when you create the connection:
mysql.createConnection({multipleStatements: true});
Then make the request with both queries
router.post('/test', function (req, res, next) {
var queries = [
"select COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = 'registros'",
"SELECT * FROM registros"
];
db.query(queries.join(';'), function (error, results, fields) {
if (error) throw error;
res.render('test', {
columnNames: results[0], // First query from array
dataRegistros: resp // Second query from array
});
});
});
But let me ask a question, why would you need to query column names when actually you query all rows and can get columns from there?

To make several queries from a single route use async npm library
npm install --save async
then use parallel method and functions to make the several queries for database with the callback.
async.parallel({
one: function(callback) {
callback(null, 'abc\n');
},
two: function(callback) {
callback(null, 'xyz\n');
}
}, function(err, results) {
if (error) throw error;
res.render('test', {
columnNames: results.one,
dataRegistros: results.two
});
});

Related

having issues calling a sql stored procedure, SelectById, from express

I'm trying to call a saved stored procedure from SQL in my node app. my server is connected and I am able to execute my selectRandom5 saved proc with no problems.
the issue I am having is when I try to do a getById where I need to declare the #Id input. I've tried a couple of variations of the function with no luck, here are two I've tried.
the error message I get with this is UnhandledPromiseRejectionWarning: RequestError: Incorrect syntax near '?'.
selectById(req, res) {
var theId = req.params.id;
// connect to your database
sql.connect(config, function (err) {
if (err) console.log(err);
// create Request object
var request = new sql.Request();
// query to the database and get the records
request.query("CALL Addresses_SelectById(?)", [theId], function (err, recordset) {
if (err) console.log("connect", err);
// send records as a response
res.send(recordset);
console.log(recordset);
});
});
}
and then there's this other function I've tried, and the error message I get from this is 'Must declare the scalar variable "#Id".'
selectById(req, res) {
var theId = req.params.id;
// connect to your database
sql.connect(config, function (err) {
if (err) console.log(err);
// create Request object
var request = new sql.Request();
// query to the database and get the records
request.query(`SET #Id = ${theId}CALL Addresses_SelectById(#Id)`, function (err, recordset) {
if (err) console.log("connect", err);
// send records as a response
res.send(recordset);
console.log(recordset);
});
});
}
I just want to be able to pass parameters to SQL to be able to create update or get by but so far I haven't been able to figure out the proper way to pass the parameters.
any help would be appreciated! thanks guys
I FOUND IT GUYS!
selectById(req, res) {
var theId = req.params.id;
// connect to your database
sql.connect(config, function (err) {
if (err) console.log(err);
// create Request object
var request = new sql.Request();
// query to the database and get the records
request.input("Id", sql.Int, theId);
request.execute("Addresses_SelectById", function (err, recordset) {
if (err) console.log("connect", err);
// send records as a response
res.send(recordset);
console.log(recordset);
});
});
I changed it to this and it works
Problem 1:
Suggested alternate syntax:
selectById(req, res) {
var theId = req.params.id;
let sql = `CALL Addresses_SelectById(?)`;
connection.query(sql, theId, (error, results, fields) => {
if (error) {
return console.error(error.message);
}
console.log(results[0]);
// Possibly stringify "results" to JSON before sending...
res.send(results);
});
}

NodeJS MySQL concat queries with responses from many model queries to one controller call

I'm having problems understanding the async methods on nodejs.
I have this fragment of code in my controller:
app.get(basePath, function (req, res, next) {
model.generateDB(function (modelErr, modelRes) {
if (modelErr) console.log('Error: ' + modelErr);
next(res.send(modelRes));
});
});
this fragment of code for the model:
generateDB: function (next) {
BDManager.query(
'INSERT INTO tableName' +
'(field1, field2) VALUES ("a", "b")',
function (err, res) {
next(err, res);
});
}
and this fragment of code for the db manager
query: function (sql, next) {
var con = mysql.createConnection(config.MySQL);
con.query(sql, function (err, res) {
if (err) next(err, null);
next(null, res);
});
con.end();
}
It works fine for me. the question is how may I have multiple queries with they're responses in the model with only one controller call, like the example (that not works):
BDManager.query(
'INSERT INTO tableName' +
'(field1, field2) VALUES ("a", "b")',
function (err, res) {
next(err, res);
});
BDManager.query(
'INSERT INTO tableName' +
'(field1, field2) VALUES ("a", "b")',
function (err, res) {
next(err, res);
});
BDManager.query(
'INSERT INTO tableName' +
'(field1, field2) VALUES ("a", "b")',
function (err, res) {
next(err, res);
});
the idea could be to get an array of errors and responses, but I don't know how to send it when all queries finish. I tried with the .then, but it seems that doesn't works (The error I get using .then is "can't use then on null").
Another solution could be to concat many queries in one, but I tried with "; " separator and doesn't works for me.
So this is using callbacks (.then is for promises). You could create a promise wrapper around it that would let you promisify it and then you could await them or use promise.all if you wanted to run them in parallel.
For example:
function promiseQuery(query, params) {
return new Promise((resolve, reject) => {
BDManager.query(query, params, function (err, res) {
if (err) return reject(err);
return resolve(res);
});
});
}
let arrayOfResponses = await Promise.all([
promiseQuery(query1, params1),
promiseQuery(query2, params2),
promiseQuery(query3, params3),
]);
Just a few things about that - you probably should be inserting values via parameterized inputs. Your SQL library should support that
Also an error will throw a rejection on this. If you want to catch those errors and push them to an array, you could do that as well with a .catch handler.
If you're not using async/await or a version of node that's compatible, you can also do:
Promise.all([]).then(arrayOfResponses => {});
As well and that will give you the array of the responses for any promises you pass in to promise.all.
There are tons of articles on how to use Promises and how they work but that should get you started.

Query in NodeJS with MySQL

I got this code and I need to create another query to send data in a form.... I tried copying this one but it didn't work ....
any idea how to proceed ?.
app.get('/', function (req2, res2) {
console.log('Welcome in console');
var sqlQuery = 'select * from transvip.transvip_regions';
// var sqlQuery2 = 'select * from transvip.transvip_agreement_favourite_address';
connection.query(sqlQuery, function (error, results, fields) {
if (error) throw error;
//console.log("results in console: ");
//console.log(results);
res.render('home', {
title: "Rounting and Assignment Grouped Trips",
results: results
});
});
});

node.js mysql result into a variable

I've been using mountebank to do some stubbing for performance testing and its an awesome tool. The functional teams have asked if it can be repurposed to support functional testing and I'd said i'd have a look.
What I want to achieve is to select from a mysql database an account number and its account balance and then return the balance to the client (in this case a jmeter harness)
function (request, state, logger) {
logger.info('GBG - getAccountBalance');
var mysql = require('mysql');
var result = '';
var con = mysql.createConnection({
host: "localhost",
user: "user",
password: "password",
database: "customer"
});
con.connect(function(err) {
if (err) throw err;
console.log("Connected!");
});
con.query('select * from accounts', function (err, rows, fields) {
if (err) throw err;
console.log(rows);
console.log('accountNumber is : ', rows[0].accountNumber);
result = rows[0].accountNumber;
});
console.log('result is : ', result);
var response = result;
return {
headers: {
'Content-Type': 'application/xml',
'Connection': 'Keep-Alive'
},
body: response
};
}
The result of the console log is:
result is :
Connected!
[ RowDataPacket { accountNumber: 777777, accountBalance: 777 } ]
accountNumber is : 777777
Not sure what I'm doing wrong and why the result is : lines comes up first despite being later in the code.
Any advice appreciated.
Full disclosure, I've been using mountebank for about two weeks so I'm a real beginner.
The function keyword inside connect and query is called callbacks, and only executed after the function itself is done. so your code would look like:
con.connect(function(err) {
if (err) throw err;
console.log("Connected!");
con.query('select * from accounts', function (err, rows, fields) {
if (err) throw err;
console.log(rows);
console.log('accountNumber is : ', rows[0].accountNumber);
result = rows[0].accountNumber;
console.log('result is : ', result);
var response = result;
});
});
and so on, but you just introduced callback hell to your code.
async is your friend.
EDIT:
following an example:
async.waterfall([
function (callback) {
//do some async function here
con.connect(function(err) {
if (err) throw err;
console.log("Connected!");
//call this when you are done
//you can even pass param to next function
callback(null,true);
});
},function (isConnected,callback1) {
if !(isConnected){
console.log("Connection failed! Skipping Query...")
callback1(null,"Error");
}
//do another async function here:
con.query('select * from accounts', function (err, rows, fields) {
if (err) throw err;
console.log(rows);
console.log('accountNumber is : ', rows[0].accountNumber);
result = rows[0].accountNumber;
callback1(null,"Complete");
});
}
], function (err,result) {
if(result == "Error"){
alert("Someting went wrong!");
}
if(result == "Complete"){
alert("Done!");
}
return 0;
});
note:I haven't written JS for awhile. Written this off of some existing code and haven't been tested. Also, Promise is also something that would help, but haven't looked into personally. BlueBird is a library for that.
The simplest way to get Data form mysql database using Promise and async await.
Get data dynamically by providing id to the SQL query.
With the help of following code snippet. First Your query will get execute fully the other process will execute.
response will be sent after execution of query is fully done. (sometimes response is sent first then execution of query completes)
async function getData(customerId){
let sql = `SELECT * FROM customer_info WHERE customerID = ${customerId}`
await connection.query(sql, (err, result) => {
data = {
CustomerId : result[0].customerID,
FirstName: result[0].FirstName,
LastName: result[0].LastName
}
})
}
function connectToDB(customerId){
return new Promise((resolve, reject) => {
getData(customerId).then(()=>resolve())
})
}
app.get('/customer/:id', (req, res) => {
let customerId = req.params.id
// Caller Function to all functions
async function callerFun(){
await connectToDB(customerId);
res.send("Execution Done");
}
callerFun();
})

Node.js returning result from MySQL query

I have the following function that gets a hexcode from the database
function getColour(username, roomCount)
{
connection.query('SELECT hexcode FROM colours WHERE precedence = ?', [roomCount], function(err, result)
{
if (err) throw err;
return result[0].hexcode;
});
}
My problem is that I am returning the result in the callback function but the getColour function doesn't return anything. I want the getColour function to return the value of result[0].hexcode.
At the moment when I called getColour it doesn't return anything
I've tried doing something like
function getColour(username, roomCount)
{
var colour = '';
connection.query('SELECT hexcode FROM colours WHERE precedence = ?', [roomCount], function(err, result)
{
if (err) throw err;
colour = result[0].hexcode;
});
return colour;
}
but of course the SELECT query has finished by the time return the value in colour
You have to do the processing on the results from the db query on a callback only. Just like.
function getColour(username, roomCount, callback)
{
connection.query('SELECT hexcode FROM colours WHERE precedence = ?', [roomCount], function(err, result)
{
if (err)
callback(err,null);
else
callback(null,result[0].hexcode);
});
}
//call Fn for db query with callback
getColour("yourname",4, function(err,data){
if (err) {
// error handling code goes here
console.log("ERROR : ",err);
} else {
// code to execute on data retrieval
console.log("result from db is : ",data);
}
});
If you want to use promises to avoid the so-called "callback hell" there are various approaches.
Here's an example using native promises and the standard MySQL package.
const mysql = require("mysql");
//left here for testing purposes, although there is only one colour in DB
const connection = mysql.createConnection({
host: "remotemysql.com",
user: "aKlLAqAfXH",
password: "PZKuFVGRQD",
database: "aKlLAqAfXH"
});
(async () => {
connection.connect();
const result = await getColour("username", 2);
console.log(result);
connection.end();
})();
function getColour(username, roomCount) {
return new Promise((resolve, reject) => {
connection.query(
"SELECT hexcode FROM colours WHERE precedence = ?",
[roomCount],
(err, result) => {
return err ? reject(err) : resolve(result[0].hexcode);
}
);
});
}
In async functions, you are able to use the await expression which will pause the function execution until a Promise is resolved or rejected. This way the getColour function will return a promise with the MySQL query which will pause the main function execution until the result is returned or a query error is thrown.
A similar but maybe more flexible approach might be using a promise wrapper package of the MySQL library or even a promise-based ORM.