Node MySQL hanging - mysql

I have my GET endpoint which is just a simple SELECT * FROM tableName and returns all the rows in the table but it keeps hanging. When I hit it in POSTMAN locally it just keep spinning with
Sending request... and the program never errors.
The get endpoint is hanging after connection.query(...) and the fourth console.log("HIT) is not printed
router.get('/allRows', async (req, res) => {
console.log("HIT")
if (req.query.tableName) {
console.log("HIT")
connection.connect((err) => {
if (err) console.log(err);
console.log("HIT")
connection.query(`SELECT * FROM ${req.query.tableName};`), (err, result, fields) => {
console.log("HIT")
if (err) console.log(err);
console.log(result)
res.status(200).json({
message: `Successfully got all data from ${req.query.tableName}`,
result: result
});
};
connection.end((err) => {
if (err)
console.error("Error when closing connection", err)
});
})
}
else {
res.status(400).json({
message: `Please provide table name`,
});
console.log('Missing table name');
}
});
I have 3 "HIT" logs at the moment, any ideas?
I noticed that if I cancel the endless request in postman and I hit the endpoint again I get a PROTOCOL_ENQUEUE_AFTER_QUIT error
EDIT
I changed my code to this:
router.get('/allRows', async (req, res) => {
console.log("HIT")
// also another guard for table name inside an array is needed
if (req.query.tableName) {
console.log("HIT")
connection.connect();
connection.query(`SELECT * FROM ${req.query.tableName}`), (err, rows, fields) => {
console.log("HIT", rows)
if (err) console.log(err);
res.status(200).json({
message: `Successfully got all data from ${req.query.tableName} LIMIT 1`,
result: rows
});
console.log("result")
};
}
else {
res.status(400).json({
message: `Please provide table name`,
});
console.log('Missing table name');
}
});
Still get the same issue and only 2 console hits... I have ran the debugger and when it gets to connection.query it just skips over it and doesn't go into the arrow function.
debugger at connection.query
debugger after connection.query

According to module docs, connection.connect is going to build live linking to database.
Just call it at server startup, and stop it when sever down.
Call connection.query when you want to solve requests.
connection.connect()
router.get(
.....
connection.query()
)
server.on(‘close’, ()=> connection.close()) // I guess
with connect error:
connection.connect(function(err) {
console.log(err.code); // 'ECONNREFUSED'
console.log(err.fatal); // true
});
router.get(
.....
connection.query()
)
server.on(‘close’, ()=> connection.close()) // I guess

Related

Node Api rest - change database dynamically|

Is it possible to change the pool config database?
I have a rest API with node/express, and I have multiple databases.
So I need that when a user.company login in my frontend, the API rest, choose the database that user should use.
My configuration file for the bank is this .env
JWT_KEY=XXXXXXX
POOL1_USER=root
POOL1_PASSWORD=xxxxxx
POOL1_DATABASE=data1
POOL1_HOST=host.domain.com
POOL1_PORT=3306
Meu arquivo db.js é este:
const mysql = require("mysql");
const pool1 = mysql.createPool({
connectionLimit: 10,
user: process.env.POOL1_USER,
password: process.env.POOL1_PASSWORD,
database: process.env.POOL1_DATABASE,
host: process.env.POOL1_HOST,
port: process.env.POOL1_PORT,
});
module.exports = { pool1 };
Is this my controllers.js file?
const mysql = require("../db").pool1;
exports.adminGroup = (req, res, next) => {
mysql.getConnection((error, conn) => {
if (error) {
return res.status(500).send({ error: error });
}
conn.query(
"INSERT INTO adminGroup SET ?",
[req.body],
(error, results) => {
conn.release();
if (error) {
return res.status(500).send({ error: error });
}
response = {
mensagem: "Group add",
grupoCriado: {
id: results.insertId,
grupo: req.body.group,
},
};
return res.status(201).send(response);
}
);
});
};
I need to dynamically change the database, as I have the same frontend for the same rest API, but I have multiple databases that can even be on different hosts.
It may be that what I'm trying to implement is not possible, so does anyone have any different suggestions?
Before you use the query to select a table from a database, you need to switch the database, use this query to achieve that.
con.query("USE your_db_name", function (err, result, fields) {
if (err) throw err;
console.log(result);
});
then after it use the query that you want like this
const mysql = require("../db").pool1;
exports.adminGroup = (req, res, next) => {
mysql.getConnection((error, conn) => {
if (error) {
return res.status(500).send({ error: error });
}
con.query("USE your_db_name", function (err, result, fields) {
if (err) throw err;
console.log(result);
});
conn.query(
"INSERT INTO adminGroup SET ?",
[req.body],
(error, results) => {
conn.release();
if (error) {
return res.status(500).send({ error: error });
}
response = {
mensagem: "Group add",
grupoCriado: {
id: results.insertId,
grupo: req.body.group,
},
};
return res.status(201).send(response);
}
);
});
};

Express.js: Reponse in catch of try/catch is never sent

I'm trying to implement a basic user registration flow using Express.js and mySQL. This is the code I have at the moment (stripped for brevity):
register(app, db) {
app.post('/register', (req, res) => {
let email = req.body.email
let password = req.body.password
try {
// add the user to the database
var q_params = [email, bcrypt.hashSync(password, 9)]
db.query("INSERT INTO users VALUES (?, ?)", q_params, (err) => {
if (err) {
throw err
}
})
} catch (err) {
// respond with an error if one is encountered
res.json({
success: false,
msg: err
})
return
}
// respond with success if everything else goes ok
res.json({
success: true,
email: email
})
});
}
The problem is that no matter the outcome of the code in the try block, I am always getting success: true. How come the error response is never triggered? Is there a better way to be handling this scenario?
I'm assuming the issue is that the nothing is waiting for the db.query() function to finish executing. It's not async and not awaiting that function to resolve. So the last res.json({}) gets hit right away.
I would try to rewrite the code to either use promises or to use that callback function passed to .query(), maybe something like this:
app.post('/register', (req, res) => {
let email = req.body.email
let password = req.body.password
// add the user to the database
var q_params = [email, bcrypt.hashSync(password, 9)]
db.query("INSERT INTO users VALUES (?, ?)", q_params, (err) => {
if (err) {
return res.json({
success: false,
msg: err
});
}
res.json({
success: true,
email: email
});
});
});

NodeJS MySql db.query command always running last

In my simple code which uses NodeJS and Express Framework along with MySql as my database, I made a simple query to the database. This is shown below vvv
app.get('/getusers', (req, res) => {
console.log('Start line')
let sql = 'SELECT * FROM users';
let query = db.query(sql, (err, results) => {
if(err) throw err;
console.log(results);
res.send('Posts fetched...');
});
console.log('End line')
});
In the terminal, the code's output is as shown below vvv
Start line
End line
[
RowDataPacket {
id: 1,
usnm: 'admin',
pswd: 'securePassword'
},
RowDataPacket {
id: 2,
usnm: 'user',
pswd: 'superSeurePassword'
}
]
Why did the lines "Start line" and "End line" run first, then the db.query command run later?
How can I fix my code so that it runs in order?
A database query is an asyncronous operation, meaning that you should await the result of the query:
const util = require('util');
const query = util.promisify(db.query).bind(db); // Make db.query able to be awaited
app.get('/getusers', async (req, res) => { // declare your function as 'async'
console.log('Start line')
let sql = 'SELECT * FROM users';
// Convert your callback to an try/catch block, so we could catch the error
try {
const results = await query(sql) // Your results will be returned straight here
console.log(results);
res.send('Posts fetched...');
} catch (err) { // If some error happens, it will be catched here
throw err;
}
console.log('End line')
});

nodejs- unable to return result to controller function

From my Model, I fetch some articles from a MySQL database for a user.
Model
var mysql = require('mysql');
var db = mysql.createPool({
host: 'localhost',
user: 'sampleUser',
password: '',
database: 'sampleDB'
});
fetchArticles: function (user, callback) {
var params = [user.userId];
var query = `SELECT * FROM articles WHERE userId = ? LOCK IN SHARE MODE`;
db.getConnection(function (err, connection) {
if (err) {
throw err;
}
connection.beginTransaction(function (err) {
if (err) {
throw err;
}
return connection.query(query, params, function (err, result) {
if (err) {
connection.rollback(function () {
throw err;
});
}
//console.log(result);
});
});
});
}
This is working and the function fetches the result needed. But it's not returning the result to the controller function (I am returning it but I'm not able to fetch it in the controller function. I guess, I did something wrong here).
When I did console.log(result) this is what I got.
[ RowDataPacket {
status: 'New',
article_code: 13362,
created_date: 2017-10-22T00:30:00.000Z,
type: 'ebook'} ]
My controller function looks like this:
var Articles = require('../models/Articles');
exports.getArticle = function (req, res) {
var articleId = req.body.articleId;
var article = {
userId: userId
};
Articles.fetchArticles(article, function (err, rows) {
if (err) {
res.json({ success: false, message: 'no data found' });
}
else {
res.json({ success: true, articles: rows });
}
});
};
Can anyone help me figure out what mistakes I made here?
I'm pretty new to nodejs. Thanks!
The simple answer is that you're not calling the callback function, anywhere.
Here's the adjusted code:
fetchArticles: function (user, callback) {
var params = [user.userId];
var query = `SELECT * FROM articles WHERE userId = ? LOCK IN SHARE MODE`;
db.getConnection(function (err, connection) {
if (err) {
// An error. Ensure `callback` gets called with the error argument.
return callback(err);
}
connection.beginTransaction(function (err) {
if (err) {
// An error. Ensure `callback` gets called with the error argument.
return callback(err);
}
return connection.query(query, params, function (err, result) {
if (err) {
// An error.
// Rollback
connection.rollback(function () {
// Once the rollback finished, ensure `callback` gets called
// with the error argument.
return callback(err);
});
} else {
// Query success. Call `callback` with results and `null` for error.
//console.log(result);
return callback(null, result);
}
});
});
});
}
There's no point in throwing errors inside the callbacks on the connection methods, since these functions are async.
Ensure you pass the error to the callback instead, and stop execution (using the return statement).
One more thing, without knowing the full requirements of this:
I'm not sure you need transactions for just fetching data from the database, without modifying it; so you can just do the query() and skip on using any beginTransaction(), rollback() and commit() calls.

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