I actually use this MYSQL Client and when I close a connection is actually never closes , so I can see in the status.
router.get('/test', function (req, res, next) {
var conn = mysql.createConnection(config);
conn.connect();
conn.query('select * from invoices ', function (err, result) {
if (err) {
throw err;
}
res.status(200).json({result: result});
conn.end();// || conn.destroy();
});
});
Move conn.end() out of the query callback - as described in node-mysql's documentation:
Every method you invoke on a connection is queued and executed in sequence.
Closing the connection is done using end() which makes sure all remaining queries are executed before sending a quit packet to the mysql server.
connection.connect();
connection.query('SELECT 1 + 1 AS solution', function(err, rows, fields) {
if (err) throw err;
console.log('The solution is: ', rows[0].solution);
});
connection.end();
Also you can use pool.
Check this link.
Connections can be pooled to ease sharing a single connection, or
managing multiple connections.
When you are done with a connection, just call connection.release()
and the connection will return to the pool, ready to be used again by
someone else.
pool.end(function (err) {
// all connections in the pool have ended
});
Related
I'm currently making a discord bot with discord.js v13. Right now I have a database where the guild.id and the standard prefix of a server are stored in. Now I want to rewrite a command which gets triggered by the prefix and the name of the command, like this '!somecommand'. Currently my prefix is defined in the file with a const variable, but I want the bot to check the database for the prefix the server has, and use this one instead. I'm checking the prefix in the database with this part of code:
pool.getConnection(function(err, connection) {
if (err) throw err;
let sql = `SELECT * FROM custom_prefix WHERE guild_id = '${message.guild.id}'`;
connection.query(sql, async function (err, result) {
if (err) throw err;
console.log(result[0].prefix)
connection.release();
});
});
The output is the current prefix of the server where the command was triggered, so far everything works fine.
But as I said I want the output of the code above to be the prefix with which the bot gets triggered.
I already tried to do it, but I'm always making a mistake.
Most of the time the bot is checking the database too slow and the result will be 'undefined'.
I dont know how I make the bot to wait for the result from the database, check if this result is really the prefix and then execute the command.
I am happy about any answer :-)
If you need any more information please let me know.
I'm guessing you did put the code that uses the result outside of the callback.
pool.getConnection(function(err, connection) {
if (err) throw err;
let sql = `SELECT * FROM custom_prefix WHERE guild_id = '${message.guild.id}'`;
connection.query(sql, async function (err, result) {
if (err) throw err;
console.log(result[0].prefix)
connection.release();
//
// Put your code that uses result[0].prefix here
//
});
});
//
// Do not put your code that uses result[0].prefix here
//
I have a question about the integration of SQLite (but in general of the DB) with Node.js with and Express framework.
From what I know, it is always good to open and close a connection to the db. But in Node.js, the processes are asynchronous (some times).
router.get("/", (req, res) => {
let db = new sqlLite.Database(path.resolve("data.db"), (err) => {
if (err) {
console.error(err.message);
}
console.log("Connected to the chinook database.");
});
db.get(`SELECT * FROM data WHERE key = '${req.query.data}'`, (err, row) => {
res.json(row);
});
db.close((err) => {
if (err) {
console.error(err.message);
}
console.log("Close the database connection.");
});
});
in this example, I open and close the connection directly within the route, so that it only handles the event in that case. Is this approach correct? what do you recommend?
In most cases, the better approach is to use some kind of connection pool, but depending on your application that may or may not matter.
That said, two things that will matter. First, you really need to close the connection during the callback, not subsequent to the query call:
router.get("/", (req, res) => {
let db = new sqlLite.Database(path.resolve("data.db"), (err) => {
if (err) {
console.error(err.message);
}
console.log("Connected to the chinook database.");
});
db.get(`SELECT * FROM data WHERE key = '${req.query.data}'`, (err, row) => {
db.close((err) => {
if (err) {
console.error(err.message);
}
console.log("Close the database connection.");
});
res.json(row);
});
});
Second, though not related to your question, is that template strings are not safe from SQL injection attacks. So you really should not take direct user input from req.body or req.query or similar and concatenate it with your query, unless you're comfortable with a malicious user destroying your DB.
To avoid the injection problem, it's a good idea to both validate that the user input falls into an acceptable range of values but also use prepared statements to properly escape potentially malicious values.
I am using node js for web service I use pool.getConnection() in my code , after use pool.getConnection() for close this connection i am using connection.release(); but in any query i am not use any function for close connection .please tell me this code is valid or not?.
pool.getConnection(function(err,connection){
connection.release();
if(!err){
email=req.user.email
connection.query('select * from users where email=?',[email],
function(err,user_detail){
if(!err)
{
connection.query('insert into message(??,time,type,user_id) values(?,?,?,?)',[messagecolumns,dbValues,time,type,user_id],
function(err,message_inserted){
if(!err)
{
console.log('Message send',message_inserted.insertId);
connection.query('select u.firstname,u.lastname,u.img_path,m.* from users u, message m where u.id=m.user_id and m.id=?',[message_inserted.insertId],
function(err,message_detail){
if(!err)
{
connection.query('select count(id) as message_count from message where appointment_request_id=?',[appointment_request_id],
function(err,total_message){
if(!err)
{
connection.query('update appointment_request set message_count=? where appointment_request_id=?',[total_message[0].message_count,appointment_request_id],
function(err,update_message_count){
if(!err)
{
}
});
}
else {
console.log('connection Error',err);
}
I feel this is not valid method for connection because from some web site I realize that after SQL query I must close connection but in this code I never use any close connection and my code are some time give me 500 server error and some time it work successfully so I have to fix this error and I want to permanently solution if anyone can help me please give me solution for this. if you have any confutation for understanding you may ask me.
A pool has a limited number of connections (Default is 10).
When you getConnection then one of those connections is removed from pool and is passed to you so that you can use it. You will call connection.release() after you are finished working with the connection. As soon as you called connection.release() the connection is passed back to the pool and is free to be used by other parts of your code. As of that it is not valid to work with this connection after you have called release on it, because it might be closed or used by another part of your code that requested a connection with getConnection (in most of the cases it might still work, but it could unexpectedly fail).
In your code you call connection.release(); at the beginning of you callback so the usage of connection after that release is not valid.
You you must not call connection.release() multiple times on the same connection.
I'm aware of the best practice of MongoDB connection pooling in NodeJS of the singleton DB connection type like this
var db = null;
var connection = function getDBConnection(callback) {
if(db) { callback(null, db) } else { MongoClient.connect( .... ) }
}
module.exports = getDBConnection;
However, what I cannot get my head around at the moment is how to handle this in a one-shot script that, say, does some pre-initialization on the documents of a certain db collection:
getDBConnection(function (err, database) {
var collection = database.collection("objects");
var allObjectsArray = collection.find( /* ... */
).toArray(function (err, objects) {
if(err != null) console.log(err);
assert.equal(null, err);
_.each(objects, function (item) {
collection.update(
{ id: item.id},
{ $set: { /* ... */ }},
function (err, result) {
if(err != null) console.log(err);
assert.equal(null, err);
}
);
});
// database.close(); <-- this fails with "MongoError: Connection Closed By Application", thrown by the update callback
});
// database.close(); <-- this fails too, thrown by the toArray callback
});
If I call the script like that, it never terminates, due to the still open connection. If I close the connection at the bottom, it fails because of, well, a closed connection.
Considering that opening a new connection for every update is not really an option, what am I missing? Keeping the connection open may be fine for webapps, but for a one-shot script called from a shell script this really doesn't work out, does it?
Sorry if this question has arisen before, I've given it some research but have not quite been able to come up with a working answer for me...
Thanks!
Julian
As a "pooled connection" there is code running to keep the connection alive and establish more connections in the pool if required under the driver connection. So much like various "server code" methods, event loop handlers have been invoked and the process does not exit at the end of your code until these are de-registered.
Therefore your two choices to call after all your code has executed are either:
Call db.close() or in your code context specifically database.close() once all is done.
Call process.exit() which is a generic call in node.js applications which will shut the whole process down and therefore stop any other current event loop code. This actually gives you an option to throw an error on exit if you want your code to be "shell integrated" somewhere and look for the exit status.
Or call both. db.close() will allow execution to the next line of code and whatever you put there will also run.
But you have to wait until everything is called, so you can cannot use synchronous loops with asynchronous code in the middle:
async.each(objects,function(item,callback) {
collection.update(
{ "_id": item._id },
{
// updates
},
callback
);
},function(err) {
if (err) throw err;
database.close();
});
i am using mysql felix node.js module.
i am using its pool connection.
i have many queries in my server side (written in node) that are written like this:
this.courtsAmount = function(date, callback){
pool.getConnection(function(err, connection) {
connection.query('SELECT MAX(id) AS result from courts where date="' + date + '"', function(err, rows, fields){
connection.release();
if (err) throw err;
if (rows[0].result)
callback(rows[0].result);
else
callback(0);
});
});
};
for some reason i keep getting this error (from all sorts of functions that are written like this):
Type Error: Cannot call method 'releaseConnection' of null
which is pointing to the 'connection.release()' line.
i really don't understand what is the problem here, as i understand from the API inside the function of pool.getConnection i am supposed to have full access to the connection. maybe it is an issue of something to have to do with timeout of the connection? i believe it is not the case because this error happens while i am actually going through my site.
another question:
do i have to deal with the option that connections will timeout if i use the pool?
and if the answer is yes, how should i do it?
thanks.
I'd recommend adding error checking before attempting to use the connection instance. I've updated your code (see my comments inline):
this.courtsAmount = function(date, callback) {
pool.getConnection(function(err, connection) {
if (err) throw err; // <-- 'connection' might be null, so add an error check here
connection.query('SELECT MAX(id) AS result from courts where date="' + date + '"', function(err, rows, fields) {
if (err) throw err; // <-- moved this line up to check for an error first
connection.release(); // <-- moved this line down so error checking happens first
if (rows[0].result)
callback(rows[0].result);
else
callback(0);
});
});
};
Also, if the date instance is coming from an untrusted source, then your code is vulnerable to SQL injection. You might consider switching to mysql2 and using a prepared statement.