Passing variables through Node MySQL function - mysql

I've created a simple function that runs a query and fetches a field value from a MySQL database in Node. I'm using the normal 'mysql' library. For some reason though, I can't pass the resulting field value out to the function. What am I doing wrong?
var mysql = require('mysql');
var connection = mysql.createConnection({
host : 'localhost',
user : 'root',
password : '',
database : 'mydb'
});
//This is my function to fetch the field
function getinfofromdb(inputID){
connection.query('SELECT * FROM `mytable` WHERE ? ORDER BY `ID` DESC LIMIT 1;', {identifierID: inputID}, function (err, rows, fields) {
if(rows[0]['filename'].length > 0){
console.log(rows[0]['filename']); // This works fine! I just can't pass it as response. :(
response = rows[0]['filename'];
}else{
response = 'none found';
}
});
return response;
}
//However, I always get that 'response' is undefined
console.log(getinfofromdb(1));
Furthermore, returning from the inner function also yields nothing.
There is no problem with the query, as I can console.log it just fine, but it just doesn't return it to the function.
if(rows[0]['filename']){
console.log(rows[0]['filename']); //This prints out just fine
return rows[0]['filename']; //Doesn't return anything
}
Update: Everything I'm trying is not yielding anything. Would someone please show me the proper way of writing a function in nodejs using the mysql library (https://github.com/mysqljs/mysql) that receives an input, runs a simple query using that input, and the value of a field in the response row? I'm going nuts.

I found the solution -- this is impossible to do.
Coming from a PHP background, not everything I'm used to write is asynchronous.
This Node JS MySQL library runs its queries asynchronously, and therefore the callback function cannot return anything. It just prints stuff such as console.log.
I guess I'm gonna revert to PHP.
How to return value from an asynchronous callback function?

Related

How to work with data returned by mysql select query in nodejs

I am working on a discord bot written in nodejs, the bot utilises a mysql database server to store information. The problem I have run into is that I cannot seem to retrieve the data from the database in a neat way, every single thing I try seems to run into some issue or another.
The select query returns an object called RowDataPacket. When googling every single result will reference this solution: Object.values(JSON.parse(JSON.stringify(rows)))
It postulates that I should get the values back, but I dont I get an array back that is as hard to work with as the rowdatapacket object.
This is a snippet of my code:
const kenneledMemberRolesTableName = 'kenneled_member_roles'
const kenneledMemberKey = 'kenneled_member'
const kenneledMemberRoleKey = 'kenneled_member_role_id'
const kenneledStaffMemberKey = 'kenneled_staff_member'
const kenneledDateKey = 'kenneled_date'
const kenneledReturnableRoleKey = 'kenneled_role_can_be_returned'
async function findKenneledMemberRoles(kenneledMemberId) {
let sql = `SELECT CAST(${kenneledMemberRoleKey} AS Char) FROM ${kenneledMemberRolesTableName} WHERE ${kenneledMemberKey} = ${kenneledMemberId}`
let rows = await databaseAccessor.runQuery(sql)
let result = JSON.parse(JSON.stringify(rows)).map(row => {
return row.kenneled_member_role_id
})
return result
}
This seemed to work, until I had to do a type conversion on the value, now the dot notations requires me to reference row.CAST(kenneled_member_role_id AS Char), this cannot work, and I have found no other way to retrieve the data than through dot notation. I swear there must be a better way to work with mysql rowdatapackets but the solution eludes me
I figured out something that works, however I still feel like this is an inelegant solution, I would love to hear from others if I am misunderstanding how to work with mysql code in nodejs, or if this is just a consequence of the library:
let result = JSON.parse(JSON.stringify(rows)).map(row => {
return row[`CAST(${kenneledMemberRoleKey} AS CHAR)`];
})
So what I did is I access the value through brackets instead of dot notation, this seems to work, and at least makes me able to store part of or the whole expression in a constant variable, hiding the ugliness.

Knex.js verifying query results in server side code

I have a function that is supposed to check if a license plate already exists in my MySQL database, but on the then-promise-return the result comes as:
result: [object Object]. How do you actually get the response of this knex query and parse it to check for a license plate existing?
var licensePlateExists = function(licensePlate){
knex.select('plate').from('licensePlates').where({'plate': licensePlate}).limit(1).then(function(result){
console.log("Result: " + result);
if(!result){
return true;
}
return false;
}).catch(function(error) {
console.error(error);
});
}
I think I might have an error related to the query itself, but I tested the raw query string in MySQL CLI and it outputs the row as expected. Maybe ordering matters in the knex query builder?
P.S. This doesn't error, it executes all the way through.
Try with
knex.select('plate').from('licensePlates').where('plate', licensePlate)
Actually using count query would be better

Node js mysql stored procedure call in a for loop

So, I'm currently using mysql npm package https://www.npmjs.com/package/mysql. I have a requirement where I'll have to call a stored procedure multiple times with the caveat that subsequent stored procedure calls depend on the previous call. Pseudo code will be as follows:
let mysql = require("mysql");
let mysqlPoolConnection = mysql.createPool({
connectionLimit: 20,
host: '0.0.0.0',
port: '3306',
user: 'user1',
password: 'pwd',
database: 'mysql_db'
});
for (let index = 0; index < params.length; index++) {
let sp_ProcedureCall = "CALL sp_StoredProcedure(?, ?, ?, ?)";
let sp_ProcedureParams = [params[index].firstParam, params[index].secondParam, params[index].thirdParam, params[index].fourthParam];
// This is where the issue is. I'd like to call the stored procedure once and then once I get a response from it then make subsequent calls. Basically, depending on the previous stored procedure result, I decide whether I continue with subsequent calls or not.
mysqlPoolConnection.query(sp_ProcedureCall, sp_ProcedureParams, (errorObj, responseObj, fieldsObj) => {
}
}
NodeJS is asynchronous, meaning your for-loop iterates without waiting for the result of the call. You need to control the flow of your program if you want to "wait" for previous results.
Look at a library like async to enabled that type of control flow. From your description, eachSeries() might be a good fit - to run a function for each value in an array, and only run one at a time. (Or reduce, depending what you need - there are other options too)

Sequelize findAll query returning incorrect results

I'm using Passport, Nodemailer, Sequelize, and Express to handle verification of user accounts who have signed up via email to the app.
To test this feature, I use Mailinator accounts to sign up, and send the email (along with a query string containing the user email and a uniquely-determined verification code) to the specified Mailinator address using Nodemailer. I then open the email in Nodemailer, click on the verification link, which updates the verification flag in the database and verifies the user.
This process works as I expect it to for exactly one user who signs up via email. When a second user signs up, the verification email is sent just as before with the username and unique verification codes in the query string, but this time, multiple users are being returned from the User.findAll query through Sequelize when the link is clicked. My query is intended to findAll possible matches of both email addresses and verification codes (since each user can only sign on with one email address and verification codes are unique), but for some reason the query is returning all matches from that query.
Here is some code for reference:
/* Sending the emails */
emails.sendActivationEmail = function(user){
const qso = {username: user.username, activationCode: user.activationCode};
const qs = querystring.stringify(qso);
const from = new helper.Email(<myEmailAddress#email.com>);
const to = new helper.Email(user.username);
const subject = 'Welcome to My Site!';
const content = new helper.Content('text/html', "<p> Thanks for signing up " +
"for our psych study, please <a href=\"http://localhost:7000/users/validate/account?" +
qs + "\">confirm your email</a></p>");
const mail = new helper.Mail(from, subject, to, content);
sendMail(mail); //invokes SendGrid mail helper function
}
/* Function invoked when user clicks on verification link in email */
emails.validateUserAccount = function(req, res){
const url = parseUrl(req.url);
const query = querystring.parse(url.query);
db.User.findAll({where: query}).then(function(matches){
if(matches.length !== 1){
res.send('error: multiple users found');
}
else{
db.User.update({
isVerified : true
},
{
where: {
username: matches[0].username
}
});
req.session.user = matches[0];
res.redirect('/');
}
}).catch(function(err){
console.error(err);
res.send(err);
});
}
Console statements in the validateUserAccount() function reveal that the query is exactly as I expect ({username: <emailAddress>, activationCode: <uniqueCode>}). However, console.log statements made in the first line after the findAll query is executed reveal that all users are being returned from the query, which should be impossible if the WHERE query is being passed in correctly, which it looks like it is from the logged statements. Why is User.findAll returning incorrect results from my query?
The problem here is that you are using the return value of querystring.parse()
As denoted in the Node docs:
Note: The object returned by the querystring.parse() method does not prototypically extend from the JavaScript Object. This means that the typical Object methods such as obj.toString(), obj.hasOwnProperty(), and others are not defined and will not work.
It's likely the where clause expects an actual JS Object.
Further, as #doublesharp mentioned, you probably want to be fetching one row and validating it, as opposed to findAlling the rows and then filtering through. Also, you should take advantage of callbacks. You're writing blocking code right now.

compare input to mysql database

item = test.query('SELECT userName FROM Database.Users WHERE userName = "user"', function (err,result){
if(err) throw err;
else if('user' == / something correct /){
console.log("TRUE");
}
console.log(result[0]);
});
What I want to do is to check if the user gives a valid username, like you would when logging in to a form of some sort. Now I might have taken the wrong approach but I've tried the following.
I tried to basically check if there is a user with username 'user', which exists in the mysql database. Then I want to simple check that the fixed input 'user' exists by comparing to the result that one gets from querying the DB. However it doesn't seem to work as the console never prints out "TRUE". However when I print out result[0] i get:
{ userName: 'user' }
Which is expected yet I can't manage to retrieve the string 'user'.
The query won't fail if there isn't a record with that username. It will only return an empty result set. Take out all the error stuff and check for number of records. You could also do a SELECT count(*) as recCnt where user = '$usr' and check the value of the returned recCnt variable.
You can try to use results[0].userName in your console.log