How to change the value of a variable inside mysql.query() method - mysql

Here is my code.
I am new to nodejs and, I am querying to the mysql database using mysql package. I have two variables i.e. hasCouponCode and isVerifiedUser and by default they are set to false. So I want to set the value of hasCouponCode to true if the couponCode exists in db and value of isVerifiedUser to true if user exists in mysql db. But I am not able to set their values to true. Then how can I change/set its value?
app.post('/', (req, res) => {
const { name, email, couponCode } = req.body;
let hasCouponCode = false, isVerifiedUser = false;
pool.getConnection((err, connection) => {
if (err) {
throw err;
}
connection.query(`SELECT * FROM coupons WHERE couponCode='${couponCode}'`, (couponError, couponRows) => {
if (couponError) {
throw couponError;
}
if (!couponRows.length > 0) {
console.log('Coupon not found...❌');
}
console.log('Coupon found...✔️');
hasCouponCode = true;
});
connection.query(`SELECT name FROM users WHERE name='${name}'`, (userError, userRows) => {
if (userError) {
throw userError;
}
if (!userRows.length > 0) {
console.log('User not found...❌');
}
console.log('User found...✔️');
isVerifiedUser = true;
});
connection.release();
});
console.log(hasCouponCode, isVerifiedUser);
res.redirect('/');
});

try:
connection.query(`SELECT * FROM coupons WHERE couponCode =10`, (couponError, couponRows) => {
if (couponError) {
throw couponError;
}
if (couponRows.length) {
console.log('Coupon found...✔️');
hasCouponCode = true;
}else{
console.log('Coupon not found...❌');
}
});
connection.query(`SELECT name FROM users WHERE name='${name}'`, (userError, userRows) => {
if (userError) {
throw userError;
}
if (userRows.length) {
console.log('User found...✔️');
isVerifiedUser = true;
}else{
console.log('User not found...❌');
}
});
connection.release();

Related

Mysql find element

I have:
const connection = mysql.createConnection({
host: process.env.APP_DATABASE_HOST,
user: process.env.APP_DATABASE_USER,
password: process.env.APP_DATABASE_PASS,
database: process.env.APP_DATABASE_NAME,
port: process.env.APP_DATABASE_PORT
});
const connectDataBase = () => {
connection.connect(function(error){
if(error){
console.log(error);
}else{
console.log('Connected');
}
});
}
exports.search = async (id) => {
try {
connectDataBase();
await connection.query(`SELECT * from devices where numberserial="${id}"`, function (err, result, fields) {
if( result ){
return true;
}
return false;
});
closeConnectionDataBase();
} catch (error) {
console.log(error)
}
};
const closeConnectionDataBase = () => {
connection.end();
}
I want that when it gets the element it returns true, but if it doesn't get the element it returns false.
for now if it gets the element it returns true, the problem I'm having is when it doesn't get the element the terminal gets stuck, what am I doing wrong??? what I want is that if the element is not found in the database it returns false

Variable doesn't get set in connection query [Node.js, MySQL]

I am having an issue with the session variable not setting. I am assuming the problem has something to do with the functions being asynchronous(async/await).
How do I make sure that session is set before jwt.sign and committing (how should I use async await or promises here)?
connection.getConnection(function(err, conn) {
try {
conn.beginTransaction(function(err) {
if (err) {
throw err
}
conn.query(`INSERT INTO USER SET username = ?, email = ?; SELECT LAST_INSERT_ID() AS id;`, [username, hashedEmail], (error, results) => {
if(error){
throw error;
} else {
// this doesn't set
req.session.verify = results[0].id;
jwt.sign(
{},
process.env.gmail_secret,
{
expiresIn: '1d',
},
(err, emailToken) => {
//...
}
)
await conn.commit(async function(error) {
if (error) {
throw err;
}
await conn.destroy();
req.flash("flash", "You have successfully created an account. The last step is to confirm your email so we know you are legit =].");
return res.redirect('/register');
});
}
})
})
} catch {
return conn.rollback(function() {
conn.destroy();
req.flash("flash", 'A server error has occurred.');
res.redirect('/register');
});
}
});

Adding bulk data to mysql database

I have a console program where the user scans in serial numbers, and those serial numbers get added to a database.
const mysql = require('mysql2');
const read = require('readline-sync');
const conn = new mysql.createConnection(config);
conn.connect(
function(err){
if(err){
throw err;
}
else{
console.log("Connection Established");
while(1){
var sn = read.question('Scan in serial number: ');
conn.query('INSERT INTO test (serial) VALUES (?);',
[sn], function(err, results, fields){
if (err){
throw err;
}
else{
console.log("Added stuff");
}
});
}
}
}
);
When the code runs it successfully connects to the database but queries the database. It continually prompts for user input.
Alternatively, I tried storing serial numbers in an array and then loops through it adding each element, like this.
const mysql = require('mysql2');
const read = require('readline-sync');
var array = [];
var sn = " ";
while (1) {
sn = read.question('Scan in serial number, or enter "done" if finished scanning');
if (sn == "done") {
break;
}
array.push(sn);
}
conn.connect(
function (err) {
if (err) {
throw err;
}
else {
console.log("Connection Established");
array.forEach(function (sn) {
conn.query('INSERT INTO test (serial) VALUES (?);',
[sn], function (err, results, fields) {
if (err) {
throw err;
}
else {
console.log("Added stuff");
}
});
});
}
}
);
In this case, it works inconsistently. Sometimes it works fine, and other times it fails to connect and throws a timeout error. Is there a better way to accomplish this and/or am I doing something wrong?
var promises = []
function dbOp(value) {
return new Promise(function(resolve, reject) {
conn.query('INSERT INTO test (serial) VALUES (?);',
[value], function (err, results, fields) {
if (err) {
return reject(err)
}
else {
console.log("Added stuff");
resolve(results)
}
}
}
conn.connect(function(err){
if(err){
throw err;
}
else{
for (i = 0; i < array.length; ++i) {
promises.push(dbOp(array[i]));
}
}
});
Promise.all(promises)
.then((results) => {
console.log("done", results);
})
.catch((e) => {
console.log(e)
});
This might be caused by short idle timeout setting in your mysql server. client.connect() is pretty much a no-op in mysql2, it connects immediately when you call mysql.createConnection(). You can change order to establish connection only after all data is collected:
const mysql = require('mysql2');
const read = require('readline-sync');
var array = [];
var sn = ' ';
while (1) {
sn = read.question('Scan in serial number, or enter "done" if finished scanning');
if (sn == 'done') {
const conn = mysql.createConnection(config);
array.forEach(function(sn) {
conn.query('INSERT INTO test (serial) VALUES (?);', [sn], function(err, results, fields) {
if (err) {
throw err;
} else {
console.log('Added stuff');
}
});
});
}
array.push(sn);
}

Express-validator check if email existed with MySQL

Im using express-validator to check if the req.body entered is valid and to check if there is duplicate email in the MySQL database
Here is my code:
router.post(
"/signup",
[
body("uemail","email is not valid")
.isEmail()
.normalizeEmail()
.custom(async (email, {req} )=>{
const queryString = "SELECT uid FROM EarlyUsers WHERE `uemail` = ?";
return await connection.query(queryString, [email], (err, rows, fields) => {
if (err) {
console.log(err)
}else {
if (rows.length != 0) {
return false
} else {
return true
}
}
});
})
,
body("uname").isLength({ min: 5 })
],
authControllers.signUp
);
I dont know why this custom validator does not work.
I've tried to throw new Error instead of return false, but it just crash the whole thing . I really need help with this
For it to work correctly instead of returning false you reject the Promise.
if (rows.length != 0) {
return Promise.reject("user already exists.");
}
I have achieved this way it might be helpful for others, I'm using sequelize :)
const User = require("../../models/User");
body('email', 'Invalid email').exists().isEmail().trim().escape().custom(userEmail=> {
return new Promise((resolve, reject) => {
User.findOne({ where: { email: userEmail } })
.then(emailExist => {
if(emailExist !== null){
reject(new Error('Email already exists.'))
}else{
resolve(true)
}
})
})
}),
I found this solution to check that the email is not duplicate:
router.post('/register',
body('email').isEmail().normalizeEmail().withMessage('The email format is not correct.').custom((email) => {
const queryString = `SELECT * FROM users WHERE user_email = "${email}"`;
return getFinalEmail(queryString).then(user => {
console.log(user);
if (user) {
return Promise.reject('E-mail already in use');
}
});
}),
// -- other validations
// .....
(req, res) => {
/* your code for this route */
}); // end of router('/register')
function getFinalEmail(param) {
return new Promise(function(resolve, reject) {
getEmailData(param, function(result) {
console.log(result);
resolve(result);
});
});
}
function getEmailData(query, callback) {
database.query(query, function(error, data){
if(data.length > 0) {
return callback(true);
} else {
return callback(false);
}
});
}
In the above code users is the name of my table and user_email is the column that email data of users are stored.

mysql node: can't set headers after they are sent

I am trying to get a list of movies in a directory, parse titles, get movie information on TMDB than check if movie info is stored in mysql database and if not stored, insert info into the database.
I am using NodeJS/Express and mysql.
Here is my code so far:
exports.checkForMovies = function (req, res, next) {
const testFolder = './test/';
var movieList = [];
var movieResultsPromise = [];
var movieResults = [];
fs.readdirSync(testFolder).forEach(file => {
movieList.push(tnp(file));
});
movieList.forEach(movie => {
var waitPromise = searchTMDB(movie.title);
movieResultsPromise.push(waitPromise);
});
Promise.all(movieResultsPromise).then(result => {
movieResults = result;
movieResults.forEach(movie => {
checkMoviesInDB(movie.id, (err, data) => {
if (err) {
console.log(err)
}
if (data && data.update === true) {
var movieObj = {
m_tmdb_id: movie.id
};
insertMoviesToDB(movieObj, (resp, err) => {
if (err) {
console.log(err);
} else {
return res.json(resp);
}
});
} else {
return res.json(data);
}
});
});
});
}
function checkMoviesInDB(id, cb) {
var sql = "SELECT * FROM ?? WHERE m_tmdb_id = ?"
var table = ['movie', id];
sql = mysql.format(sql, table);
connection.query(sql, function (err, rows) {
if (err) {
return cb(err);
}
if (rows.length > 0) {
return cb(null, {
success: true,
update: false,
message: 'Movies up to date!'
})
} else {
return cb(null, {
update: true,
message: 'Updating database!'
})
}
});
}
function insertMoviesToDB(movie, cb) {
var sql = "INSERT INTO ?? SET ?";
var table = ['movie', movie];
sql = mysql.format(sql, table);
connection.query(sql, function (err, rows) {
if (err) {
return cb(err);
} else {
return cb(null, {
success: true,
message: 'Movie database updated!'
})
}
});
}
function searchTMDB(title) {
return new Promise((resolve, reject) => {
https.get(config.tmdbURL + title, response => {
var body = "";
response.setEncoding("utf8");
response.on("data", data => {
body += data;
});
response.on("end", () => {
body = JSON.parse(body);
resolve(body.results[0]);
});
response.on("error", (err) => {
reject(err);
});
});
});
}
After code execution it inserts movie info in the database or responses with "Movies up to date" but I am getting this error and NodeJS crashes:
Error: Can't set headers after they are sent.
Any help is appreciated, thanks!
EDIT!
This is the new code and I am still getting the same error...
exports.checkForMovies = function (req, res) {
const testFolder = './test/';
var movieList = [];
var movieResults = [];
fs.readdirSync(testFolder).forEach(file => {
movieList.push(tnp(file));
});
var movieObj = movieList.map(movie => {
var tmp = [];
return searchTMDB(movie.title).then(data => {
tmp.push(data);
return tmp
});
});
var checkDB = Promise.all(movieObj).then(moviesData => {
moviesData.map(movieData => {
checkMoviesInDB(movieData[0]).then(checkResponse => {
if (!checkResponse.movieToInsert) {
res.json(checkResponse);
} else {
var insertArray = checkResponse.movieToInsert;
var inserting = insertArray.map(movie => {
var movieObject = {
m_tmdb_id: movie.id,
m_name: movie.title,
m_year: movie.release_date,
m_desc: movie.overview,
m_genre: undefined,
m_poster: movie.poster_path,
m_watched: 0
};
insertMoviesToDB(movieObject).then(insertResponse => {
res.json(insertResponse);
});
});
}
});
});
});
}
function checkMoviesInDB(movie) {
var moviesToInsert = [];
return new Promise((resolve, reject) => {
var sql = "SELECT * FROM ?? WHERE m_tmdb_id = ?"
var table = ['movie', movie.id];
sql = mysql.format(sql, table);
connection.query(sql, function (err, rows) {
if (err) {
return reject(err);
}
if (rows.length === 0) {
moviesToInsert.push(movie);
resolve({
success: true,
movieToInsert: moviesToInsert
});
} else {
resolve({
success: true,
message: 'No movie to insert'
});
}
});
});
}
function insertMoviesToDB(movie) {
return new Promise((resolve, reject) => {
var sql = "INSERT INTO ?? SET ?";
var table = ['movie', movie];
sql = mysql.format(sql, table);
connection.query(sql, function (err, rows) {
if (err) {
return reject(err);
} else {
resolve({
success: true,
message: 'Movie added!'
});
}
});
});
}
function searchTMDB(title) {
return new Promise((resolve, reject) => {
https.get(config.tmdbURL + title, response => {
var body = "";
response.setEncoding("utf8");
response.on("data", data => {
body += data;
});
response.on("end", () => {
body = JSON.parse(body);
resolve(body.results[0]);
});
response.on("error", (err) => {
reject(err);
});
});
});
}
Auth.js
const config = require('./config');
const jwt = require('jsonwebtoken');
module.exports = function (req, res, next) {
var token = req.body.token || req.params.token || req.headers['x-access-token'];
if (token) {
jwt.verify(token, config.secret, function (err, decoded) {
if (err) {
return res.json({
success: false,
message: 'Failed to authenticate token.'
});
} else {
req.decoded = decoded;
next();
}
});
} else {
return res.status(403).send({
success: false,
message: 'Please login in to countinue!'
});
}
};
Hope this helps:
// Bad Way
const checkForMovies = (req, res) => {
const movieList = ['Braveheart', 'Highlander', 'Logan'];
movieList.forEach(movie => {
res.json(movie); // Will get Error on second loop: Can't set headers after they are sent.
})
}
// Good Way
const checkForMovies = (req, res) => {
const movieList = ['Braveheart', 'Highlander', 'Logan'];
const payload = { data: { movieList: [] } };
movieList.forEach(movie => {
payload.data.movieList.push(movie);
});
// send res once after the loop with aggregated data
res.json(payload);
}
/* GET home page. */
router.get('/', checkForMovies);