ER_BAD_NULL_ERROR when inserting value into column with nodejs + mysql - 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.

Related

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

How to return result of db from a nested functions in nodejs

I want the result on other file but not getting how to return it
function getUsers(){
console.log("Fetching all user data");
const connection = getConnection();
const sql = "SELECT * FROM users";
var result = connection.query(sql,(err, rows, fields) =>{
if(err){
console.log("Failed to get users data");
res.sendStatus(500);
throw err;
}
console.log("Fetched Users Successfully");
return rows;
})
return result;
}
This is a standard asynchronous function problem.
return rows will not assign rows to the result variable. Second argument of query() function is a callback function and it indicates a block of code that will be executed after rows are fetched. It means that result of the query is only visible inside callback block.
You can fix it in 2 ways:
Write all your code that uses SQL result inside callback function block (You can call another function at that point and pass result as argument for example).
This method is simpler if you are new to javascript programming. I see that you want to use function getUsers() in another place. If you choose this approach, best way would probably be to pass a callback to the getUsers() function and then invoke it in the callback of the query() method.
Example:
getUsers(callback){
const connection = getConnection();
const sql = "SELECT * FROM users";
connection.query(sql,(err, rows, fields) => callback(rows))
}
mainFunction(req,res){
getUsers(doSomethingWithUsers)
}
doSomethingWithUsers(users){
...
}
This is of course, oversimplified pattern, but the idea should be clear.
Research about promises and how they handle async functions. This will require you to "wrap" you function body into Promise object type.
They will allow you to write something like this:
mainFunction(){
getUsers().then(result => ....);
// or even
const users = await getUsers();
}
EDIT:
To wrap "return value of promise", or as we say "to resolve a promise", you can wrap function the following way:
function getUsers(){
console.log("Fetching all user data");
const connection = getConnection();
const sql = "SELECT * FROM users";
return new Promise( (resolve,reject) => {
var result = connection.query(sql,(err, rows, fields) =>{
if(err){
// this will cause promise to "fail"
reject(err);
}
console.log("Fetched Users Successfully");
// this will tell javascript that promise is finished
// and rows are accesable in then()
resolve(rows);
})
})
}
function mainFunction(){
const result = getUsers()
.then(rows =>{/** this will happen if resolve(rows) is called */})
.catch(error => {/** this will be executed if reject(err) happens
*/});
}
// or... (Try/Catch is required since "await" silently fails
async function asyncMainFunction(){
try{
const rows = await getUsers();
// You can use rows from resolve() here;
}catch(error){
// here, reject is called
}
}
Here is a link where you can read more about promises:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
You are not getting the result because the code is asynchronous. So, you have to use async/await to get the result. Your code should look like this:-
async function getUsers(){
console.log("Fetching all user data");
const connection = await getConnection();
const sql = "SELECT * FROM users";
try {
var result = await connection.query(sql);
console.log("Fetched Users Successfully");
return result;
} catch (err) {
console.log("Failed to get users data");
res.sendStatus(500);
throw err;
}
}
Finally, call this function like this:-
var output = await getUsers();
But make sure that you call this line in an async function.
Hope this helps!
create file for function : getUsers.js
module.exports = async getUsers(){
const connection = getConnection();
const sql = "SELECT * FROM users";
var myPromise = () => {
return new Promise((resolve, reject) => {
connection.query(sql, query.params, function (error, results, fields) {
error ? reject(error) : resolve(results);
})
});
}
var result = await (myPromise());
return result;
}
require this file and call function :
var getUsers = require('..path to getUsers');
var data = getUsers().then((data)=>{
}).catch((error)=>{
console.log('error',error)
return error;
});
using callback :
or using callback function :
module.exports = function getUsers(callback){
const connection = getConnection();
const sql = "SELECT * FROM users";
connection.query(sql, query.params, function (error, results, fields) {
if(error){ callback(error,null)}
if(!error && results){
callback(null,results)
}
});
}
require file :
var getUsers = require('..path to getUsers');
call it this way :
getUsers(err,data)=>{
if(err){
return res.send(err);
}
if(!err && data){
return res.send(data);
}
}
function getUsers(callback) {
console.log("Fetching all user data");
const connection = getConnection();
const sql = "SELECT * FROM users";
connection.query(sql, (err, rows, fields) => {
if (err) {
console.log("Failed to get users data");
res.sendStatus(500);
callback(err, null);
}
console.log("Fetched Users Successfully");
callback(null, rows)
})
}
// USE ABOVE FUNCTION AS BELOW...
getUsers(function(err, rows) {
if(err){
console.error(err);
}
console.log(rows);
})

Node mysql cannot get a response on a query

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.

Lambda function MySQL result not working on NodeJs 8.10

I have a code in Node 6.10 and it is working...
But If I convert it to Node 8.10 it's not working
var mysql = require("mysql");
var connection = mysql.createConnection({
host: " localhost",
user: "root",
password: "",
database: "parser_db"
});
exports.handler = async event => {
connection.connect();
let response = {
statusCode: 400,
body: { Method: "Invalid", event }
};
var readTable = "SELECT * FROM documents where id = " + mysql.escape(1);
connection.query(readTable, function(err, results, fields) {
if (err) throw err;
else {
response = {
statusCode: 200,
body: { results }
//body: { results }
};
console.log(response);
return response;
}
});
};
Can some one please help me to detect the problem. It is also not working if I do the MySQL query in separate file and return the result set.
Note : If I print the result using console.log(response) instead returning it's
showing the correct result.
The problem is that you are returning response from within the connection.query() callback function. That makes response the return value for the callback function, not the return value for the outer Lambda function.
One way to restructure this code is as follows:
exports.handler = async (event) => {
connection.connect();
return new Promise((resolve, reject) => {
const readTable = `SELECT * FROM documents where id = ${mysql.escape(1)}`;
connection.query(readTable, (err, results, fields) => {
if (err) {
reject(err);
} else {
resolve({statusCode: 200, body: {results}});
}
});
});
};
In addition to #jarmod's answer, You can also use the util.promisify method to promisify connection.query so that you can use the await keyword, to make the code simpler
const util = require('util');
exports.handler = async (event) => {
connection.connect();
const readTable = `SELECT * FROM documents where id = ${mysql.escape(1)}`;
const connQueryPromisified = util.promisify(connection.query).bind(connection);
const result = await connQueryPromisified(readTable);
return {statusCode: 200, body: {results}};
};

var is undefined if using var keyword node

Building a small MVC. When I'm receiving results back from my model, the variable that I'm using to send to my view is undefined if I use the "var" keyword. If I don't use the keyword the object comes through just fine. What is happening?
Controller
const homeModel = require('../models/homeModel.js');
exports.index = function(req, res){
homeModel.getAllStores(function (err, res) {
if (err) return err;
stores = res; // Works
var stores = res // Undefined
})
console.log(stores);
res.render('home', {stores: stores});
}
Here is the Model
const db = require('../db.js');
exports.getAllStores = function(done) {
db.query('select * from stores;', (err, rows) => {
if (err) return done(err);
let resultJson = JSON.stringify(rows);
resultJson = JSON.parse(resultJson);
return done(null, resultJson);
})
}
You need to move the declaration of stores to the function enclosing homeModel.getAllStores(). This is because JavaScript is function (lexically) scoped, so a variable will be scoped to the nearest enclosing function. You can read more about how variables that are declared using var work on MDN.
In Node.js, if you don't provide the var keyword before your variable then it is globally scoped to the module in which it is running, this is why console.log(stores) works when you use stores = res and not var stores = res.
To properly scope your variable using var, just move your declaration to the function being exported.
Additionally, your console.log() and res.render() calls are occurring before the callback function for homeModel.getAllStores() is executed and setting stores = res. Since res.render() and console.log() will only work as expected within the callback to homeModel.getAllStores() you can simplify index() and the callback to homeModel.getAllStores().
const homeModel = require('../models/homeModel.js')
exports.index = (req, res) => {
return homeModel.getAllStores((err, stores) => {
if (err) {
throw err
}
console.log(stores)
return res.render('home', {stores})
})
}
You could also use util.promisify() and async/await to write this a little more straightforward.
const {promisify} = require('util')
const getAllStores = promisify(require('../models/homeModel').getAllStores)
const index = async (req, res) => {
let stores
try {
stores = await getAllStores()
} catch (err) {
console.error(err)
return res.sendStatus(500)
}
return res.render('home', {stores})
}
module.exports = {index}
Here is an example with Promise.all() waiting for the results from multiple queries with a hypothetical UserModel with getAllUsers() that works identically to homeModel.getAllStores() but queries a users table.
const {promisify} = require('util')
const getAllUsers = promisify(require('../models/userModel').getAllUsers)
const getAllStores = promisify(require('../models/homeModel').getAllStores)
const index = async (req, res) => {
let queryResults
try {
queryResults = await Promise.all([getAllStores, getAllUsers])
} catch (err) {
console.error(err)
return res.sendStatus(500)
}
let [stores, users] = queryResults
return res.render('home', {stores, users})
}
module.exports = {index}