Queries inside of a connection query callback - node.js

I am trying to fetch a table, whose name is defined in another table and return the results.
I have defined a database module with these methods:
var mysql = require("mysql");
var config = require("../config/database.js");
module.exports = {
pool: mysql.createPool({
host: config.host,
user: config.user,
database: config.database,
password: config.password,
}),
getConnection: function(callback) {
this.pool.getConnection(callback);
},
fetch: function(table, callback) {
this.getConnection(function(err, connection) {
if(err) {
callback(err);
} else {
connection.query("SELECT * FROM ??", table, callback);
connection.release();
}
});
},
};
I am trying to fetch the table and then the "sub" table like so:
db.fetch("foo", function(err, rows) {
if(err) {
throw err;
} else {
_.each(rows, function(row) {
db.fetch(row.tbl, function(err, result) { console.log(err, result); });
});
}
});
However the inner-fetch callback is never called.
Why is this? I suspected I needed to close the first connection before establishing a second so I tried taking the each loop outside but encountered things becoming out of sync.

Related

Callback limit Node.JS? Or am I missing something?

Good day, I recently had help learning how to make things wait using callbacks, however now it's almost as if I hit a limit on how many can be used, but I can't seem to find information on this?
If I ran this code without tryToCreateAccount having a callback, it will connect, check and work as intended. As soon as I make tryToCreateAccount have a callback param, it appears to enter Connect.Connect (only sometimes) but then never query's.
Backend:
const mysql = require('mysql');
const connection = mysql.createConnection({
host: 'host',
user: 'user',
password: 'pass',
database: 'db'
});
export function tryToCreateAccount(login, password, passwordConfirm, callback)
{
checkAccountNameAvailable(login, connection, function(err, accountNameAvailable)
{
callback(err, accountNameAvailable);
});
}
function checkAccountNameAvailable(login, connection, callback)
{
var accountNameAvailable = true;
console.log("Checking account name", login);
connection.connect(function (err)
{
console.log("Checking Connect Method");
if(err) callback(err);
connection.query("SELECT login FROM accounts WHERE login = ?", login, function (err, result)
{
if (err) callback(err);
if(result.length > 0) accountNameAvailable = false;
console.log("returning ", accountNameAvailable);
callback(null, accountNameAvailable);
connection.end();
});
});
}
Front End:
tryToCreateAccount($w('#input1').value, $w('#input2').value, $w('#input3').value, function (err, callback)
{
if(callback)
{
console.log("Was True");
}
else
{
console.log("Was False");
}
});
UPDATED CODE:
Backend:
const mysql = require('mysql');
const pool = mysql.createPool(
{
connectionLimit : 10,
host : 'host',
user : 'user',
password : 'pass',
database : 'db'
});
export function tryToCreateAccount(login, password, passwordConfirm, callback)
{
checkAccountNameAvailable(login, pool, function(err, accountNameAvailable)
{
if(err)
{
console.log(err);
callback(err, null);
}
callback(err, accountNameAvailable);
});
}
function checkAccountNameAvailable(login, pool, callback)
{
var accountNameAvailable = true;
console.log("Checking account name", login);
pool.getConnection(function (err, connection)
{
console.log("Made a connection.");
if(err)
{
console.log(err);
callback(err, null);
connection.destroy();
}
connection.query("SELECT login FROM accounts WHERE login = ?", login, function (err, result)
{
console.log("Checking Query Method");
if (err)
{
console.log(err);
callback(err, null);
}
if(result.length > 0) accountNameAvailable = false;
console.log("returning ", accountNameAvailable);
callback(null, accountNameAvailable);
connection.destroy();
});
});
}
Frontend is the same
Output:
Checking account name testaccount

How to get RAISE INFO/NOTICE in Knex from node js?

I am using Knex query builder and Postgres as my data base.
I need to get the output from a raise notice or raise info from a Postgres function or procedure.
raise notice 'This is my Log';
we need to set notice after pool created, for that we need to use afterCreate function.
for your references
https://github.com/knex/knex/issues/4241
The sample code is below.
var pConn = {
host: 'SERVER',
port: 'PORT',
user: 'USER',
password: 'PASSWORD',
database: 'DATABAENAME'
};
var query = "select * from pglog_test()";
try {
const knex = require('knex')({
client: 'pg',
connection: pConn,
pool: {
afterCreate: function (conn, done) {
conn.query('select 1 as result', function (err, result) {
conn.on('notice', function (msg) {
// here we can get the pg procedure logs (raise notice/raise info)
console.log('logs from postgress' + msg);
});
done(err, conn);
});
}
}
});
// procedure calling
knex.raw(query).then(function (result) {
console.log(result);
}).catch(function (error) {
console.log(error);
});
} catch (error) {
console.log(error);
}

Invalid object name 'dbo.tbl_user' after running sql(azure) query from nodejs app

I am getting error Invalid object name dbo.tbl_user.while running a query on the Azure database from a nodejs app.My code which runs is following.
const pool = new sql.ConnectionPool(DatabaseConfig.config);
pool.connect().then(function () {
//6.
debugger;
var request = new sql.Request(pool);
//7.
request.query("select * from [dbo].[tbl_user]").then(function (recordSet) {
debugger;
console.log(recordSet);
sql.close();
}).catch(function (err) {
//8.
debugger;
console.log(err);
sql.close();
});
}).catch(function (err) {
//9.
debugger;
console.log(err);
});
My connection string is :
config: {
server: 'azureserver',
options: {
database: 'cccc',
encrypt: true,
port: 1433
},
user: 'ccc',
password: 'ccccc'
}
what is the mistake I am doing here? Thanks in advance for the help.
I tested your code on my side but did not reproduce your issue.
Here is my test code:
const sql = require('mssql')
const config = {
server: '***.database.windows.net',
database: '***',
user: '***',
password: '***',
options: {
database: '***',
encrypt: true,
port: 1433
}
}
const pool = new sql.ConnectionPool(config);
pool.connect().then(function () {
//6.
debugger;
var request = new sql.Request(pool);
//7.
request.query("select * from [dbo].[Student]").then(function (recordSet) {
debugger;
console.log(recordSet);
sql.close();
}).catch(function (err) {
//8.
debugger;
console.log(err);
sql.close();
});
}).catch(function (err) {
//9.
debugger;
console.log(err);
});
Query result on the portal:
Run query.js :
You need to make sure the table name is correct, it's not related to spelling case.
Hope it helps you.

How do I convert this code using promises?

I am new to Nodejs.I want to convert this code to promises (nodejs).This includes four callback function get(),abc1(),pqr(),xyz(). It gives error of "cannot read property 'then' of undefined" Can anyone fix it? I am trying it to convert into promises from this example here
var jwt = require('jwt-simple');
var mysql = require('mysql');
var async = require('async');
var Promise = require('bluebird');
var connection = mysql.createConnection({
host: 'localhost',
port: 3306,
database: 'abc',
user: 'root',
password: ''
});
var auth = {
login: function (req, res) {
var username = req.body.username || '';
var password = req.body.password || '';
console.log(req.body);
//This is get() function
function get(err, rows) {
connection.connect(function (err) {
if (err) {
console.error('error connecting: ' + err.stack);
return;
} else {
console.log("connected to database");
connection.query("SELECT count(id) as count from abc where name=? AND email=?", [username, password], function (err, rows) {
if (err) {
throw err
} else {
b = rows;
console.log(b);
}
});
}
});
}
//this is abc1() function
function abc1(err, rows) {
console.log("onresult");
if (err) {
throw err;
console.log("error in Query");
} else {
if (rows[0].count != 1) {
//xyz(result,xyz);
res.json({
"status": 401,
"message": "Invalid credentials"
});
} else {
connection.query("SELECT email from abc where name=? AND email=?", [username, password], function (err, rows) {});
//res.json(genToken("ayush"));
}
}
}
//This is xyz() function
function xyz(err, rows) {
if (err) {
console.log(err);
}
console.log(rows);
connection.query("SELECT name from abc where name=? AND email=?", [username, password], function (err, rows) {});
}
//This is pqr() Function
function pqr(err, rows) {
if (err) {
console.log(err);
}
console.log(rows);
}
get()
.then(function (rows) {
// do something...
//console.log("hellow1");
return abc1();
})
.then(function (rows) {
// do something...
console.log("hellow2");
return xyz();
})
.then(function (rows) {
// the third and final async response
console.log("hellow3");
return pqr();
})
.then(function (rows) {
// the third and final async response
console.log("hellow4");
})
.fail(function (err) {
// handle any error resulting from any of the above calls
throw err;
})
.done();
}
}
With arguments (err, rows), all four functions appear to be written as nodebacks and we can make a shrewd guess as to what the original working code looked like.
Without modification, nodebacks can only be used as nodebacks. Inserting them raw into a promise chain won't work.
But your functions will work in a promise chain after :
Promisifying the underlying asycn functions, ie connection's methods.
Calling, in the functions, the connection.methodAsync() version of the methods instead of connection.method().
Returning a promise from each of your functions.
The whole thing actually works better with a little renaming/refactoring to start with a connect() function rather than get().
var jwt = require('jwt-simple');
var mysql = require('mysql');
var async = require('async');
var Promise = require('bluebird');
var connection = mysql.createConnection({
host: 'localhost',
port: 3306,
database: 'abc',
user: 'root',
password: ''
});
//Promisify `connection`.
//Lucky you, Bluebird has a `.promisifyAll()` method.
Promise.promisifyAll(connection);
//Now, `auth` will be something like this :
var auth = {
login: function (req, res) {
var username = req.body.username || '';
var password = req.body.password || '';
//Let's assume you want to build an object containing various user details
var authObj = {
'userName': userName,
'email': null, //to be set later
'name': null //to be set later
};
function connect() {
return connection.connectAsync().catch(function(err) {
throw 'Error connecting: ' + err.stack;
});
}
function abc1() {
return connection.queryAsync("SELECT count(id) as count from abc where name=? AND email=?", [username, password]).then(function (rows) {
if (rows[0].count != 1) {
throw new Error('Invalid credentials');
}
});
}
function xyz() {
return connection.queryAsync("SELECT email from abc where name=? AND email=?", [username, password]).then(function(rows) {
return rows[0].email;
});
}
function pqr() {
return connection.queryAsync("SELECT name from abc where name=? AND email=?", [username, password]).then(function(rows) {
return rows[0].name;
});
}
return connect()
.then(abc1)//check credentials
.then(xyz)//get email
.then(function (email) {
authObj.email = email;
return pqr();//get name
})
.then(function (name) {
authObj.name = name;
return authObj;//make authObj available to auth.login()'s caller.
})
.catch(function (err) {
// handle any error resulting from any of the above calls.
console.log(err);
throw err;//make the error available to auth.login()'s caller.
});
}
}
As you will see, err doesn't feature in the code until the bottom of auth.login(). It is the nature of promisified nodebacks that errors propagate down the promise chain's error path, and don't need to be handled mid-chain unless you need to do something like mid-chain error recovery.
Whereas this is good for learning how to construct a promise chain, in practice you appear already to know name and email at the outset, and you would probably choose to login and obtain other user details in one hit with suitable SQL.

node-mysql doesn't reuse connections

I'm using the connection pool in this way:
var pool = mysql.createPool({
host: config.db.host,
port: config.db.port,
user: config.db.user,
password: config.db.password,
database: config.db.database,
connectionLimit: config.db.connectionLimit
});
exports.api_point = function(req, res) {
pool.getConnection(function(err, connection) {
if (err) {
console.error('error acquiring connection', err);
var result = {};
result.error = err.code;
res.json(result);
return;
} else {
var query = connection.query('SELECT * FROM tableName', function(err, rows) {
connection.release();
var result = {};
if (err) {
console.error('error executing query: ' + err.stack);
result.error = err.message;
} else {
result.data = rows;
}
res.json(result);
return;
});
}
});
};
Problem:
Yet, after all the connections (defined by connectionLimit, e.g. 20) are created, the next call to pool.getConnection() hangs until Express returns: "GET /api_point - - ms - -" (after ~10s).
I've tried replacing connection.release(); with connection.destroy(); with no effect.
How can I solve this?
node-mysql version:
"mysql": "~2.5.1",
Btw. I track connections being created with:
var connCount = 0;
pool.on('connection', function(connection) {
console.log('connCount:', ++connCount);
});
Whatever I changed, nothing seemed to work until I switched to using "express-myconnection" as middleware (as described here: http://teknosains.com/i/simple-crud-nodejs-mysql).
In short: you get the connection from the request and no need to release it afterwards as the middleware cares about that.
So, my code is now (only important parts):
app.js:
var myconnection = require('express-myconnection');
var mysql = require('mysql');
app.use(
myconnection(mysql, {
host: config.db.host,
port: config.db.port,
user: config.db.user,
password: config.db.password,
database: config.db.database,
connectionLimit: config.db.connectionLimit
}, 'request')
);
api.js:
exports.api_point = function(req, res) {
req.getConnection(function(err, connection) {
if (err) {
console.error('error acquiring connection', err);
var result = {};
result.error = err.code;
res.json(result);
return;
} else {
var query = connection.query('SELECT * FROM tableName', function(err, rows) {
var result = {};
if (err) {
console.error('error executing query: ' + err.stack);
result.error = err.message;
} else {
result.data = rows;
}
res.json(result);
return;
});
}
});
};

Resources