rely on the result of a query to run another nodejs mysql - mysql

Hey guys I have the following node code and it works fine
import express from 'express';
import connection from '../index.js'
const router = express.Router();
router.get('/allTemplates', function (req, res) {
let queryString="select count(*) as exist from users where userName='bob'";
let query = connection.query(queryString, (error, result) => {
if(error) {throw error;}
res.json(result);
})
});
module.exports = router;
what I want to do is react to this with something like
if(exists==1){error='sorry but that user already exists';} else {
queryString="insert into users (userName, email, address) values('bob', 'emailAddress#email.com', 'address')";
let query = connection.query(queryString, (error, result) => {
if(error) {throw error;}
res.json(result);
})
}
I come from a php background so this is all very new and the async of node freaks me out but I have to use it for my new job. How would I react to a result of one query and run another one based on the outcome.

I put the mysql library in a variable called database and I am using async await to run queries. In the database file I connect to the database and set up my variables like so:
const mysql = require("mysql");
const util = require("util");
const awsConfig = {
host: process.env.RDS_HOST,
user: process.env.RDS_USER,
password: process.env.RDS_PASSWORD,
database: process.env.RDS_DATABASE
};
const connection = mysql.createConnection(awsConfig);
connection.query = util.promisify(connection.query.bind(connection));
connection.end = util.promisify(connection.end.bind(connection));
module.exports = connection;
Than i use async await to run queries and use the results to run or not run others. like so:
let result;
let sqlStatement ="";
result = await database.query(sqlStatement);
let userExists = result[0].exist;
sqlStatement =
"SELECT COUNT(*) AS exist FROM user where userName=" +
database.escape(req.body.userName);
if(userExists==0){
result = await database.query("INSERT INTO user SET ?", [req.body]);
}
hope this helps someone else

Related

undefined value if no result returned in API Mysql query

I'm working on my first API every and first time every using Node.js.
I have this code which is test code. I'm trying to get a Chemist users name and password from my system.
If the query runs and a row exists, this works fine, however I'm try to get a console log error or even a status result and I can't.
It just dies on the const section because there IS no row.
I have tried moving the declarations under the IF section but that also results in errors!
Thanks for any point in the right direction.
const express = require('express');
const router = express.Router();
var config = require('./../../databaseConfig');
var connection= config.connection;
router.get('/:id',(req,res) => {
connection.query('SELECT * FROM tblChemists WHERE chemistID = ?',[req.params.id],(err,rows,fields)=>{
const chemName = rows[0].chemistName;
const chemPass = rows[0].chemistpass;
if(!err)
console.log(chemName),
console.log(chemPass),
res.status(201).json({
message: 'Chemist Found',
name: chemName,
pass: chemPass
});
else
console.log(err);
})
});
module.exports = router;
You need to check to see if rows has data before trying to access it. You should also look at wrapping everything in a try-catch
router.get('/:id', (req, res) => {
connection.query('SELECT * FROM tblChemists WHERE chemistID = ?', [req.params.id], (err, rows, fields) => {
if (rows && Array.isArray(rows) && rows.length) {
const chemName = rows[0].chemistName
const chemPass = rows[0].chemistpass
} else {
return res.status(500).send('no rows returned')
}
if (!err) {
console.log(chemName),
console.log(chemPass),
res.status(201).json({
message: 'Chemist Found',
name: chemName,
pass: chemPass
})
} else {
console.log(err)
}
})
})

Using MySQL db functions (?) with SQLite (Node.js)

I'm using a tutorial to do JWT/bcryptjs auth and then INSERT into a SQlite
table.
Thing is the tutorial is for MySQL and I get errors like db.query is not a function
and db.escape is not a function
The db :
const sqlite3 = require('sqlite3').verbose()
const DBSOURCE = "./src/db/db.sqlite"
let db = new sqlite3.Database(DBSOURCE, (err) => {
if (err) {
// Cannot open database
console.error(err.message)
throw err
}else{
console.log('Connected to the SQLite database.')
}
});
module.exports = db
Example query :
db.query(
`SELECT * FROM users WHERE LOWER(username) = LOWER(${db.escape(
req.body.username
)});`,
(err, result) => {
if (result.length) {
return res.status(409).send({
msg: 'This username is already in use!'
});
} else { .........
My best guess is that the functions are different?
How do I get this right?
There are a lot of proprietary functions in MySQL that will not work with standard SQL in other database systems.
That is just the beginning of the differences between Mysql and SQLite
Provide some query examples and we may be able to assist you with each one.
-- update after your addition of query code...
Here is an example of sqlite-nodejs
const sqlite3 = require('sqlite3').verbose();
// open the database
let db = new sqlite3.Database('./db/chinook.db');
let sql = `SELECT * FROM users WHERE LOWER(username) = LOWER(?)`;
db.all(sql, [req.body.username], (err, rows) => {
if (err) {
throw err;
}
rows.forEach((row) => {
console.log(row.name);
});
});
// close the database connection
db.close();

Node JS MySQL wait for results

I'm quite new to Node JS, and I'm trying to build an API based on MySQL.
In one of my routers I'm trying to inject an insert query and based on it, get the new generated task id from mysql.
The problem is that the second query is not waiting for the response and sometimes I'm getting an error because taskId variable is undefined because it still didn't get the results from the first query.
the problematic variable that is not getting it's value correctly is taskId.
I'm attaching my code for your review, thanks for your help!
As requested: I'm attaching my required moudle as well:
const dotenv = require('dotenv');
const mysql = require('mysql');
dotenv.config();
var connection = mysql.createPool({
host: process.env.DB_HOST,
user: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
database: process.env.DB_TABLE,
port: process.env.DB_PORT
});
module.exports = connection;
router.post('/new', auth, async (req, res) => {
const uid = req.body.uid;
const taskName = req.body.taskName;
const description = req.body.description;
const createdDate = req.body.createdDate;
const estimatedDate = req.body.estimatedDate;
const status = req.body.status;
let taskId = '';
addTaskQuery = `INSERT INTO task (title,description,status) VALUES ('${taskName}','${description}','${status}')`;
findTaskIdQuery = `SELECT id FROM task WHERE title = '${taskName}'`;
try {
// Injecting into task table
await connection.query(addTaskQuery, (err, results) => {
if(err) {
console.log(err);
return res.send(JSON.stringify({data: err}));
}
})
// Getting the new inserted task id
await connection.query(findTaskIdQuery, (err, results) => {
if(err) {
console.log(err);
return res.send(JSON.stringify({data: err}));
}
taskId = JSON.stringify(results[0].id);
})
// Injecting into havetask table
await connection.query(`INSERT INTO havetask (id,userId,taskId) VALUES (${taskId},${uid},${taskId})`, (err, results) => {
if(err) {
console.log(err);
return res.send(JSON.stringify({data: err}));
}
})
}
catch(err) {
console.log(err);
return res.status(401).json({ msg: 'An error occured while tried to add task'});
}
})
The mysql package you use does not support Promises (=== it doesn't do async / await). So your await statements don't wait, they just fall through.
You need to try a package that handles async / await. This one might do the trick.

Node callback returns mysql result but i cant print to the user with actions on google for dialogflow

I created an intent to get user information based on the ID he provides as param. Using a mysql module i can process the query and get the result. With a callback i can get the result to the main function but the agent ignores once i pass to a conv.ask(). What am i doing wrong?
This is my first script with node. I tried declaring pesquisar_aluno() in a variable so i could use in the main function but it retuns null.
const express = require('express');
const bodyParser = require('body-parser')
const mysql = require('mysql')
const {
dialogflow,
SignIn,
SimpleResponse
} = require('actions-on-google')
app.intent('pesquisar.alunos', (conv, params) => {
const aluno = params.aluno
conv.ask('Vamos pesquisar')
pesquisar_aluno(aluno,function(result){
var resposta = result
console.log(resposta) // returns the result
conv.ask(resposta) // ignores it
})
console.log(resposta) // returns undefined
})
function pesquisar_aluno(aluno,callback)
{
var connection = mysql.createConnection({
host : process.env.MYSQL_HOST,
user : process.env.MYSQL_USER,
password : process.env.MYSQL_PASS,
database : process.env.MYSQL_DB
})
connection.connect()
var query = `SELECT * FROM aluno WHERE id_aluno = "${aluno}"`
connection.query(query, function (error, results, fields)
{
if(error) throw error
var usuario = `RA =>${results[0].id_aluno} Nome => ${results[0].nome}`
if(callback) return callback(usuario)
})
}
Expect conv.ask(resposta) to print the result to the user but its not printing anything
Edit: Changed to promises. It worked!Thanks to Nick Felker and Prisoner
app.intent('pesquisar.alunos', (conv, params) => {
const aluno = params.aluno
conv.ask('Vamos pesquisar')
let nome = pesquisar_aluno_promise(aluno).then(function(results) {
return results[0].nome
}).catch((err) => setImmediate(() => { throw err; }))
return nome.then(function(result){
conv.ask(result)
})
})
async function pesquisar_aluno_promise(aluno)
{
return new Promise(function (resolve,reject) {
var connection = mysql.createConnection({
host : process.env.MYSQL_HOST,
user : process.env.MYSQL_USER,
password : process.env.MYSQL_PASS,
database : process.env.MYSQL_DB
})
connection.connect()
var query = `SELECT * FROM aluno WHERE id_aluno = "${aluno}"`
connection.query(query, function (error, results, fields)
{
if (error) {
return reject(error)
}
resolve(results)
})
})
}
As Nick suggested in the comments, you need to use Promises when you are doing asynchronous operations.
Additionally, however, you need to return that Promise from your Intent Handler so the Intent Dispatcher knows to wait for the result before continuing.
In your case, this can just be adding return, so it might look something like this:
return nome.then(function(result){
console.log(result) //works
conv.ask(result) //should work now
})

discord.js/node.js make code wait until sql query returns result

I am working on a discord.js bot, and I'm storing a bunch of information on various servers in a database. The problem is, that the code doesn't wait for the database to return the results. In the current situation, I'm trying to check if the server specific prefix checks out.
I tried using async and await at various places, but those didn't work. If I could, I'd rather not use .then(), because I don't really want to put all the commands inside a .then().
const { Client, Attachment, RichEmbed } = require('discord.js');
const client = new Client();
const mysql = require("mysql");
const config = require("./config.json")
var con = mysql.createConnection({
host: 'localhost',
user: 'root',
password: '',
database: 'botdb'
})
client.on("ready", () => {
console.log("I'm ready")
})
client.on("message", message => {
if (message.author.bot) return;
if (message.channel.type === 'dm') return;
let msg = message.content.split(" ");
let command = msg[0];
let prefix;
con.query(`SELECT * FROM serversettings WHERE ServerID = ${message.guild.id}`, (err, rows) => {
if (err) throw err;
prefix = rows[0].Prefix;
console.log(prefix)
})
console.log(`Prefix: ${prefix}, Command: ${command}`)
if (command === `${prefix}examplecommand`) {
//Do something
}
//Other code that uses prefix and command
}
It should log the prefix first, and then the Prefix: ${prefix}, Command: ${command} part, but it does it the other way around, so the examplecommand doesn't work.
Your result is caused by the fact that what's outside your query callback is executed immediately after the call. Keep in mind the mysql module is callback-based.
Possible Solutions
Place the code inside the callback so it's executed when the query is completed.
Wrap the query in a promise and await it.
function getGuild(guildID) {
return new Promise((resolve, reject) => {
con.query(`SELECT * FROM serversettings WHERE ServerID = '${guildID}', (err, rows) => {
if (err) return reject(err);
resolve(rows);
});
});
}
const [guild] = await getGuild(message.guild.id) // destructuring 'rows' array
.catch(console.error);
console.log(guild.prefix);
Use a Promise-based version of a MySQL wrapper, like promise-mysql. You could use it the same way as the code above, without worrying about coding your own Promises.
const [guild] = await con.query(`SELECT * FROM serversettings WHERE serverID = '${message.guild.id}'`)
.catch(console.error);
console.log(guild.prefix);