Node mysql cannot get a response on a query - mysql

I have a trouble when i pass a function inside my query. When i run my code without the function just work without any problem. With it on postman is stuck on "Sending request"
Example:
save() {
return db.query(
{
sql: "INSERT INTO contenido (titulo, extencion_archivo, fecha_publicacion) VALUES (?, ?, ?)",
values: [this.titulo, this.extension, this.fecha]
}, function(err, res, fields) {
//More code
}
);
}
Following code work without any problem:
save() {
return db.query(
{
sql: "INSERT INTO contenido (titulo, extencion_archivo, fecha_publicacion) VALUES (?, ?, ?)",
values: [this.titulo, this.extension, this.fecha]
}
);
}
How i call save method:
exports.addVideo = (req, res, next) => {
const titulo = req.body.titulo;
const extension = req.file.mimetype.split("/")[1];
const fecha = new Date();
const videoUrl = req.file.filename;
const video = new Videos(null, titulo, extension, fecha, videoUrl);
video.save().then(() => {
res.json('sending')
})
};

You are using .then on function save() which is not promise returning function. I think that may be the reason for you not getting any response for your postman request.
Try running this code :
function save() {
return new Promise((resolve, reject) => {
db.query(
{
sql: "INSERT INTO contenido (titulo, extencion_archivo, fecha_publicacion) VALUES (?, ?, ?)",
values: [this.titulo, this.extension, this.fecha]
}, function (err, res, fields) {
if (err) {
console.log("Error Occurred :", err);
reject();
}
console.log("Successfully Sent :", res);
resolve();
}
);
})
}
and
exports.addVideo = (req, res, next) => {
const titulo = req.body.titulo;
const extension = req.file.mimetype.split("/")[1];
const fecha = new Date();
const videoUrl = req.file.filename;
const video = new Videos(null, titulo, extension, fecha, videoUrl);
video.save().then(() => {
res.json('sending')
}).catch(() =>{
res.json('Error Occurred')
})
};
Please try this if it works well and good else let me know I will try to help you around this.

Related

ER_BAD_NULL_ERROR when inserting value into column with nodejs + mysql

I am trying to insert a value using postman to test my api. My class table have 2 columns (classId which is auto incremented and classes). However, I kept getting this error message and I am unsure of how to solve this.
This is the postman result.
This is my database table class.
Here is my code.
const db = require('../config/databaseConfig');
const adminDB = {};
adminDB.createClass = (classes, callback) => {
var dbConn = db.getConnection();
dbConn.connect(function (err) {
if (err) {
return callback(err, null);
}
const query = "INSERT INTO practiceme.class (classes) VALUES (?)";
dbConn.query(query, [classes], (err, results) => {
dbConn.end();
if (err) {
console.log(err);
return callback(err, null);
} else {
return callback(null, results);
}
});
});
};
module.exports = adminDB;
const express = require("express");
const router = express.Router();
const adminDB = require("../model/admin");
router.post("/createClass", (req, res, next) => {
var {classes} = req.body;
adminDB.createClass(classes,(err, results) => {
if (err) {
return res.status(500).send({ err });
}
return res.status(200).json(results);
}
);
}
);
module.exports = router;
You're sending the classes variable as a query parameter. To access it from req, you should use req.query instead of req.body.
Change from:
var {classes} = req.body;
to:
var {classes} = req.query;
Or, in Postman, you select the Body tab and then type the body of the request in JSON format. Then your actual code should work.

AWS Lambda stops execution in the middle of the code

I am trying to trigger csv file upload in s3 and insert the data from the file to database using lambda.
Most of the times code executes successfully if i run the code back to back in couple of seconds gap.
But sometimes the problem i face is the code stops execution at console console.log('about to get the data'); and ignore rest of the code and sometimes mysql connection gets time out.
I can find that the problem occurs only when i test the lambda code with more than 20 seconds of gap. So, i guess this is a cold start problem.
I don't want to miss even a single s3 trigger. So, i need help to find flaw in my code that is causing this problem.
const AWS = require('aws-sdk');
const s3 = new AWS.S3({region: 'ap-south-1', apiVersion: '2006-03-01'});
var mysql= require('mysql');
var conn = mysql.createPool({
connectionLimit: 50,
host: 'HOST',
user: 'USER',
password: 'PASSWORD',
database: 'DATABASE'
})
async function mainfunc (event, context, callback) {
console.log("Incoming Event: ", JSON.stringify(event));
const bucket = event.Records[0].s3.bucket.name;
const filename = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, ' '));
const params = {
Bucket: bucket,
Key: filename
};
console.log('about to get the data'); //Code stops here some times
return await getresult(params);
};
async function getresult(params){
var result = await s3.getObject(params).promise();
var recordList = result.Body.toString('utf8').split(/\r?\n/).filter(element=>{
return element.length> 5;
})
recordList.shift()
var jsonValues = [];
var jsonKeys = result.Body.toString('utf8').split(/\r?\n/)[0]
recordList.forEach((element) => {
element = element.replace(/"{2,}/g,'"').replace(/, /g,"--").replace(/"{/, "{").replace(/}"/, "}").replace(/,/g, ';').replace(/--/g,', ').split(';');
jsonValues.push(element)
});
var lresult = await query(jsonKeys, jsonValues);
return lresult;
}
async function query(jsonKeys, jsonValues){
var qresult = await conn.getConnection(function(err, connection) {
if (err){
console.log(err,'------------------------------------');// Sometimes i get Sql Connection timeout error here
} else {
console.log("Connected!");
var sql = "INSERT INTO reports ("+jsonKeys+") VALUES ?";
connection.query(sql, [jsonValues], function (err, result) {
if (err){
console.log(err);
connection.release()
return err;
} else {
console.log("1 record inserted");
console.log(result);
connection.release()
return result;
}
});
}
})
}
exports.handler = mainfunc
I have solved the issue by using promise in the "query" function
function query(jsonKeys, jsonValues){
return new Promise(function(resolve, reject) {
conn.getConnection(function (err, connection) {
if (err) {
console.log(err, '------------------------------------');
}
else {
console.log("Connected!");
var sql = "INSERT INTO principal_reports (" + jsonKeys + ") VALUES ?";
connection.query(sql, [jsonValues], function (err, result) {
if (err) {
console.log(err);
connection.release();
reject(err)
}
else {
console.log("1 record inserted");
console.log(result);
connection.release();
resolve(result)
}
});
}
})
})
}
and changed the code
var lresult = await query(jsonKeys, jsonValues);
to
var lresult = await query(jsonKeys, jsonValues).then(data =>{
return data;
}).catch(error =>{
return error;
});

Array push doesn't work in promise node.js

I have previously attempted to wrap this code in callbacks, async what ever the language has to offer. However, I am still getting nowhere.
The problem is, that members remains empty, even though it should be pushed with info.
channels however, works fine.
Weirdly, the
console.log(values);
prints before the
console.log(result);
Interestingly though,
console.log(result)
does have the correct data, but where I do
console.log(members)
it is empty.
I have tested, the query is all correct, it is literally a problem with the pushing and getting the result earlier than it currently is returned (I assumed Promises would mean things would be more in order, but maybe my understanding is wrong).
Here is the full code:
module.exports.controller = (query, helper, cache, Database, mysql, config) => {
return async (req, res) => {
let zone = req.body.zone;
let returning = {};
if(!zone){
return res.json(helper.responseJson(false, 'Missing parameter "zone"'));
}
function teleport_available(channel_name){
if(channel_name.indexOf("Nadaj / UsuĊ„") === -1){
return true;
}else{
return false;
}
}
await mysql.query("SELECT * FROM flamespeak_pbot.zones WHERE zone = '"+ zone +"'", async (err, row) => {
if (err) throw err;
row = row[0];
if (row.length == 0) {
return res.json(helper.responseJson(false, "Zone not found."));
} else {
var channelsPromise = new Promise((resolve, reject) => {
const channels = [];
JSON.parse(row.assignGroupAdditional_ch).forEach(additionalCh => {
cache.channelList.filter(channel => channel.cid == additionalCh).forEach(mainCh => {
mainCh.propcache.teleport_available = teleport_available(mainCh.propcache.channel_name);
mainCh.propcache.subchannels = [];
cache.channelList.filter(channel => channel.pid == additionalCh).forEach(subCh => {
subCh.propcache.teleport_available = teleport_available(mainCh.propcache.channel_name);
mainCh.propcache.subchannels.push(subCh);
});
channels.push(mainCh.propcache);
});
});
resolve(channels);
});
var membersPromise = new Promise((resolve, reject) => {
let members = [];
query.serverGroupClientList(row.serverGroupID)
.then(serverGroupList => {
serverGroupList.forEach(member => {
var sql = "SELECT * FROM teamspeak_clientDbList WHERE client_database_id = '" + member.cldbid + "'";
mysql.query(sql, function (err, result) {
if (err) throw err;
console.log(result);
members.push(result);
})
});
})
.then(() => {
console.log(members);
resolve(members);
});
});
}
Promise.all([channelsPromise, membersPromise]).then(function(values) {
console.log(values);
returning = {
'channels' : values[0],
'members' : values[1],
'pbot' : row,
};
res.send(helper.responseJson(true, returning));
});
});
};
};
With respect, your mixture of callbacks, promises, and async / await is very hard to follow. You'd be wise to simplify it. (Or risk having your name cursed by the person who must maintain this code later.)
The callback in your second mysql.query() method is called whenever MySQL wants (whenever the query finishes or fails). But you don't resolve any promise or return from an async method within that callback's code. So, your console.log(result) shows a correct result, but your other code doesn't get access to that result; your Promise.all resolves before that method is called.
Something like this would, in general, be the right thing to do:
var sql =
"SELECT * FROM teamspeak_clientDbList WHERE client_database_id = '" +
member.cldbid + "'";
mysql.query(sql, function (err, result) {
if (err) throw err;
console.log(result);
members.push(result);
resolve (result); // <<< add this line
})
But in your case it probably won't work: your function query.serverGroupClientList() seems to return a Promise. You didn't show us that function, so it's hard to guess how to weave that into your logic.
query.serverGroupClientList(row.serverGroupID)
.then(serverGroupList => {
let members = [];
serverGroupList.forEach(member => {
var sql = "SELECT * FROM teamspeak_clientDbList WHERE client_database_id = '" + member.cldbid + "'";
mysql.query(sql, function (err, result) {
if (err) throw err;
console.log(result);
members.push(result);
})
});
resolve(members);
})
Try this
SELECT * FROM teamspeak_clientDbList
While iterating serverGroupList, the db Query on each element is asynchronous. Hence empty members.
Moreover foreach expects a synchronous function so you will have to use for-loop or for-of to use async-await feature.
var membersPromise = new Promise((resolve, reject) => {
let members = [];
query.serverGroupClientList(row.serverGroupID)
.then(async (serverGroupList) => {
console.log("serverGroupList: ", serverGroupList);
for (let index = 0, arrLen = serverGroupList.length; index < arrLen; index++) {
let member = serverGroupList[index];
var sql = "SELECT * FROM teamspeak_clientDbList WHERE client_database_id = '" + member.cldbid + "'";
await mysql.query(sql, async function (err, result) {
if (err) throw err;
console.log(result);
members.push(result);
});
}
console.log(members);
resolve(members);
});
});
Nested Code can be improved if you write a wrapper function for db queries which returns a promise.
function fireQuery(mysql, query, params = []) {
return new Promise((resolve, reject) => {
return mysql.query(query, params, (err, data) => {
if (err) return reject(err);
return resolve(data);
});
});
}
// ex -1
let rows = await fireQuery(mysql,query,params);
if(rows.length == 0) {} // your code
// ex-2
let member = await fireQuery(mysql,query2,params2);
members.push(member);

How to pass the correct params in PUT method in REST server (NodeJS, MySQL)

I'm implement a simple high score board with RESTful, the server uses NodeJS and MySQL. I get the problem when implement the PUT method while the others (GET, POST, DELETE...) work well in both client and POSTMAN as I expected.
In MySQL, I create a table with only 2 values are "username" and "score".
Here is my route code:
'use strict';
module.exports = function(app) {
let userCtrl = require('./controllers/UserControllers');
// routes
app.route('/users')
.get(userCtrl.get)
.post(userCtrl.store);
app.route('/users/:username')
.get(userCtrl.detail)
.put(userCtrl.update)
.delete(userCtrl.delete);
app.route('/leaderboard')
.get(userCtrl.top);
};
Here is my controller source code:
'use strict';
const util = require('util');
const mysql = require('mysql');
const db = require('./../db.js');
module.exports = {
get: (req, res) => {
let sql = 'SELECT * FROM leaderboard';
db.query(sql, (err, response) => {
if (err) throw err;
res.json(response);
});
},
store: (req, res) => {
let sql = 'INSERT INTO leaderboard SET ? ';
// sql = 'INSERT INTO leaderboard_log SET '
let data = req.body;
db.query(sql, [data], (err, response) => {
if (err) throw err;
res.json({message: 'Insert success!'});
});
},
// the 'update' here works well in POSTMAN
update: (req, res) => {
let sql = 'UPDATE leaderboard SET ? WHERE username = ?';
let data = req.body;
let username = req.params.username;
db.query(sql, [data, username], (err, response) => {
if (err) throw err;
res.json({message: 'Update success!'});
});
}
};
The client in javascript uses PUT method
function httpPut(theUrl, data, callbackSuccess, callbackError) {
$.ajax({
type: "PUT",
url: theUrl,
success: callbackSuccess,
error: callbackError,
dataType: "json",
crossDomain: true
});
}
// how to pass the params 'username, 'newScore' to httpPUT ?!?
function updateUser(username, newScore) {
let data = {};
data['username'] = username;
data['score'] = newScore;
httpPut(URL_PUT_USER + username, data, function(data) {
// success
console.log("success update");
}, function(data) {
// fail
console.log("update error");
});
}
The problem is the function
updateUser(username, newScore)
which I don' know how to pass the param so that the update: (req, res) will understand.
Note that I tested using POSTMAN to update the record and the update: (req, res) works well.
Any help is appreciate. Thank you!.
PS: here is the error on server:
simple_leaderboard\node_modules\mysql\lib\protocol\Parser.js:80
throw err; // Rethrow non-MySQL errors
^
PUT maps to store operation, where your sql is defined as :
let sql = 'INSERT INTO leaderboard SET ? ';
This is not a valid SQL insert statement.
You probably want :
let sql = 'INSERT INTO leaderboard(username, data) VALUES(?, ?)';
let username = req.params.username;
let data = req.body;
db.query(sql, [username, data], ...

Extend variables outside MySQL query function in NodeJS

I tried to run a function which returns a value back but am getting undefined.
function getMessageId(myId, user){
$query = "SELECT * FROM startMessage WHERE (userFrom = '"+myId+"' AND userTo = '"+user+"') OR (userFrom = '"+user+"' AND userTo = '"+ myId+"')";
connect.query($query, function(error, rows){
sql = rows[0];
console.log(sql);
return sql.id;
})
}
// running the function
msgId = getMessageId(userFrom, userTo);
console.log(msgId);
Now when I tried to console.log the sql I get the expected result like
{
id : 3,
userFrom : 3,
userTo : 1,
type : "normal",
date : "2017-06-25 06:56:34",
deleted : 0
}
But when I console.log the msgId I get undefined. I am doing this on NodeJS, please any better solution?
Short answer, Because its an asynchronous operation.
The outer console.log happens before the getMessageId returns.
If using callbacks, You can rewrite getMessageId as
let msgId
function getMessageId(myId, user, callback){
$query = "SELECT * FROM startMessage WHERE (userFrom = '"+myId+"' AND userTo = '"+user+"') OR (userFrom = '"+user+"' AND userTo = '"+ myId+"')";
return connect.query($query, function(error, rows){
sql = rows[0];
console.log(sql);
callback(sql.id);
})
}
function setMsgId(id) {
msgId = id;
}
And then call it as,
getMessageId(userFrom, userTo, setMsgId);
Further I would suggest you look into Promises.
Which would very well streamline the flow.
Using Promises, getMessageId should look something like
function getMessageId(myId, user){
$query = "SELECT * FROM startMessage WHERE (userFrom = '"+myId+"' AND
userTo = '"+user+"') OR (userFrom = '"+user+"' AND userTo = '"+
myId+"')";
const promise = new Promise((resolve, reject) => {
connect.query($query, function(error, rows){
sql = rows[0];
console.log(sql);
resolve(sql.id);
})
return promise.
}
Post this, You can use it as
getMessageId(myId, user).then((msgId) => console.log(msgId))
create a wrapper for mysql use
// service/database/mysql.js
const mysql = require('mysql');
const pool = mysql.createPool({
host : 'host',
user : 'user',
password : 'pass',
database : 'dbname'
});
const query = (sql) => {
return new Promise((resolve, reject) => {
pool.query(sql, function(error, results, fields) {
if (error) {
console.error(error.sqlMessage);
return reject(new Error(error));
}
resolve(results);
});
});
}
module.exports = { query };
then call from another script with async funcion and await
// another file, with express route example
const db = require('/service/database/mysql.js')
module.exports = async (req, res) => { // <-- using async!
let output = []; // <-- your outside variable
const sql = 'SELECT * FROM companies LIMIT 10';
await db.query(sql) // <-- using await!
.then(function(result) {
output = result; // <-- push or set outside variable value
})
.catch(e => {
console.log(e);
});
// await db.query("next query" ...
// await db.query("next query" ...
// await db.query("next query" ...
res.json(output);
}
This is probably NOT a proper way, and a hack, but sharing for information purpose (you may not like to use this)
Simply use an if else and call the function once inside the query (if true), and call it outside (if false)
if (id != null) {
// Get Details
const query = pool.execute('SELECT * FROM `sometable` WHERE `id` = ?', [id], function(err, row) {
if (err) {
console.log(err)
return
} else {
if (row && row.length) {
// Do Something
}
}
})
} else {
// Do Something
}