How to properly use node-mysql? - mysql

I just started using node-mysql2 and I am confused how to use it properly. Examples:
(Implicitly established connection)
var express = require("express"),
app = express();
var mysql = require("mysql2");
var conn = mysql.createConnection({ ... });
app.VERB("/", function(req, res){
conn.query('SELECT 1+1 as test1', function(err, rows) {
// Show data to user...
// No .end() needed?
});
});
app.listen(8000);
second example:
var express = require("express"),
app = express();
var mysql = require("mysql2");
var conn = mysql.createConnection({ ... });
conn.connect(function(err){ ... }); // Is it right place to put it here? Or it has to go inside the callback below?
app.VERB("/", function(req, res){
conn.query("SELECT 1+1 as test1", function(err, rows){
// Show data to user...
conn.end(); // .end() necessary?
});
});
app.listen(8000);

Although I haven’t used node-mysql2, it is compatible with the original node-mysql module, so the same usage patterns apply.
The best way to use it is with connection pooling. That way, the MySQL client will create and destroy connections as needed. Your job is to call connection.release() when you no longer need a connection:
var express = require("express"),
app = express();
var mysql = require("mysql2");
var pool = mysql.createPool({ ... });
app.VERB("/", function(req, res){
pool.getConnection(function(err, conn) {
if (err) { /* handle the error and bail out */ }
conn.query('SELECT 1+1 as test1', function(err, rows) {
conn.release(); /* the connection is released back to the pool */
if (err) { /* handle the error */ }
else { /* show data to user */ }
});
});
});
app.listen(8000);
If your app runs “forever” (a web site for example) then you don’t need to call pool.end(). If you’re not using a connection pool, you don’t need to call connection.end() after each request. You wouldn’t want to: that would give you the overhead of establishing/tearing down the MySQL connection on every request!
If your app does not run “forever” (a command-line utility, for example), then call pool.end() or connection.end() just before you exit back to the command-line.

Related

Connect MySQL database with node JavaScript application

I make a node JavaScript app and deploy it on cPanel using SSH.
App is working fine without database but when I connect the app with database on cPanel (GoDaddy) it takes times and shows the message "Error establishing a database connection".
My connection code
const mysql = require('mysql');
const express = require('express');
const app = express();
var pool = mysql.createConnection({
host: 'localhost',
user: '<MY_USER_NAME>',
password: '<MY_PASSWORD>',
database: '<DB_NAME>'
});
pool.connect(function(err) {
if (err) throw err;
else{
console.log("Connected!");
}
});
module.exports = pool;
route where DB interact,but lost the connection.
app.post('/loginn', (req, res) => {
var id = req.body.id
console.log("user_id= "+id);
var sql = "select * from users where id NOT IN ('" + id + "') ";
pool.query(sql, function (err, rows) {
if (err) throw err;
else {
res.render('allusers', {
users: rows,
user_id:id
})
}
});
});
This answer is going to take the form of a debugging journey, because that's the only way I can see to get to the bottom of your issue.
Let's do a dead-simple representation of your app to make sure that you can send a query to MySQL and receive a response from a route-handler in Express. Setup your app like this:
const mysql = require('mysql');
const express = require('express');
const app = express();
const PORT = // define the PORT for your host
var connection = mysql.createConnection({
host: 'localhost',
user: '<MY_USER_NAME>',
password: '<MY_PASSWORD>',
database: '<DB_NAME>'
});
connection.connect(function(err) {
if (err) console.error(err);
console.log("Connected!");
});
app.get('/db-test', (req, res, next) => {
var id = // fill in a user_id that you know exists
var sql = `SELECT * FROM users WHERE id NOT IN ('${id}') `;
console.log(sql); // confirm you are sending the sql request you believe you should be sending
connection.query(sql, function (err, results, fields) {
if (err) console.error(err);
console.log(`results: ${results}\nfields: ${fields}`);
});
});
app.listen(PORT);
And then hit the route /db-test from your app, and see what happens. If this works, then we will have at least proved that you CAN make requests between Express and MySQL. Right now, I'm not sure you can, so I'm not sure what to debug.

Angular 4 - display date from database

I need display data in table from MySql database, but I dont know how it do this.
I tried found something example or example application with source code, but I nothing found.
Maybe someone help me with this?
I tried with node.js express:
var mysql = require('mysql');
var https = require('https');
var con = mysql.createConnection({
host: "https://adress to database",
user: "user",
password: "password",
database: "db"
});
con.connect(function(err) {
if (err) throw err;
console.log("Connected!");
});
But i get error:
Error: getaddrinfo ENOTFOUND
here is a simple way to get data from mySQL and export it as json:
var http = require('http');
var mysql = require('mysql');
var bodyParser = require("body-parser");
var express = require('express');
var app = express();
var pool = mysql.createPool({
host: 'db location',
user: 'username od db',
password: 'something',
database: 'yourdatabase',
port:3306
});
// define rute
var apiRoutes = express.Router();
var port = 9000;
apiRoutes.get('/', function (req, res) {
res.json({ message: 'API works' });
});
apiRoutes.get('/data', function (req, res, next) {
pool.getConnection(function (err, connection) {
if (err) {
console.error("error hapened: " + err);
}
var query = "SELECT * FROM imena ORDER BY id ASC";
var table = ["imena"];
query = mysql.format(query, table);
connection.query(query, function (err, rows) {
connection.release();
if (err) {
return next(err);
} else {
res.json({
success: true,
list_users: rows
});
}
});
});
});
app.use('/api', apiRoutes);
// starting
app.listen(port);
console.log('API radi # port:' + ' ' + port);
But i still suggest that you start using noSQL databases like firebase because of they are simple and faster.
In order to show data from MySQL Database, you need to provide application interface(s) to Angular environment and only then Angular can use the data. There are few techniques in which you can design interfaces, REST is the most popular though.
First you need to understand that Angular is Front-End framework and it can only send requests to backend such as Node js, PHP etc.Thus, first you need to chose your backend. Node is popular with express js module, but if you still don't have mySQL set, go for firebase real time database. If you decide node js => express => mySQL check tutorial online.

How does Node's require() resolve, such that persisted database pooling in Express works?

I feel that I am lacking some basic understanding of how nodejs' architecture is put together so that the code below runs with no problems. I'm going to lay out a simple app. Can you guys help me with the questions at the end?
Notes:
I am using the mysql package https://github.com/mysqljs/mysql
node app.js is run from the command line.
Inside app.js is this:
const Express = require("express");
const Path = require("path");
const app = Express();
// Require controller modules
var book_controller = require('../controllers/bookController');
var author_controller = require('../controllers/authorController');
router.get('/book', book_controller.books_get);
router.get('/author', book_controller.authors_get);
app.listen(5000, function(){
console.log("Server started on port 5000");
});
Inside bookController:
var getConnection = require('../config/mysql');
// Display list of all books
exports.book_get = function(req, res) {
getConnection(function(err, con) {
query = 'SELECT * FROM books';
con.query(query, function(err, result) {
if (err) throw err;
con.release();
res.render('page/authors', { result:result});
});
})
};
Inside authorController:
var getConnection = require('../config/mysql');
// Display list of all books
exports.authors_get = function(req, res) {
getConnection(function(err, con) {
query = 'SELECT * FROM authors';
con.query(query, function(err, result) {
if (err) throw err;
con.release();
res.render('page/books', { result:result});
});
})
};
Inside mysql.js
var mysql = require('mysql');
var pool = mysql.createPool({
connectionLimit: 100,
connectTimeout: 5000,
acquireTimeout: 5000,
queueLimit: 30,
host: 'localhost',
user: '',
password: '',
database: '',
multipleStatements: true,
});
var getConnection = function(callback) {
pool.getConnection(function(err, connection) {
if (err) return callback(err);
callback(err, connection);
});
};
pool.on('acquire', function(connection) {
console.log('Connection %d acquired', connection.threadId);
});
module.exports = getConnection;
That's the layout. Here are the questions:
How do separate files requiring the same dependency interact? Books and Author controllers both need to require and access the mysql pool, assumedly from different users. Is a new copy of the MySQL object instantiated?
How does the state from the pool persist to the next connection?
How do separately required files interact? Books and Author controllers both need to require and access the mysql pool, assumedly from different users. Is a new copy of the MySQL object instantiated?
No, a new copy of the object will not be created on every call to require.
In Node, modules are loaded as needed and the resulting export object is cached for subsequent calls to require, so you'll get the exact same reference to getConnection every time you call require('../config/mysql'). The lines before module.exports = getConnection; run only the first time that the module is required.
How does the state from the pool persist to the next connection?
Because the exported getConnection is cached, that function will always refer to the same pool object, so both of your controllers are referring to the same pool.

Node.JS and MySQL - queries lock up and execute extremely slowly

I am getting strange behavior using Node.JS and MySQL with this driver - https://github.com/mysqljs/mysql
Essentially, I have a button on the frontend that triggers an app.get that makes a query in the database and I can happily use the results in my backend.
This works nicely, until I press the button 4-5 times in a second, where as the queries lock up and I have to wait for 2-3 minutes until they continue executing. I have a similar write function that behaves the same way.
Is it possible this is a problem, because I'm trying to execute the exact same query asynchronously? I.e. do I have to limit this from the front end or is it a backend problem?
Any ideas on how to debug what exactly is going on?
// database.js
var mysql = require('mysql');
var pool = mysql.createPool({
connectionLimit: 100,
host : 'localhost',
user : 'secret',
password : 'secret',
database : 'mydb'
});
exports.getConnection = function(callback) {
pool.getConnection(function(err, connection) {
callback(err, connection);
});
};
// dbrw.js
var con = require('../config/database');
function read(id, done) {
con.getConnection(function(err, connection){
if(!err){
connection.query("SELECT * FROM users WHERE id = ?",[id], function(err, rows) {
connection.release();
if (err)
done(err);
if (rows.length) {
console.log("rows " + JSON.stringify(rows));
done(rows[0].progress);
};
});
}
else {
console.log(err);
}
});
}
exports.read = read;
// routes.js
var dbrw = require('./dbrw.js');
app.get('/read', isLoggedIn, function(req, res) {
dbrw.read(req.user.id, function(result) {
console.log(result);
});
});
// Frontend - angular app.js
$scope.tryread = function() {
$http.get('/read');
}
Thanks in advance for any input.
I see a few issues:
function read(id, done) {
con.getConnection(function(id, connection){...}
}
Notice how you overwrite the id passed to read by giving that same name to an argument of the callback to getConnection.
Also, your Express route doesn't actually end the request by sending back a response, which will make your browser time out the connection. At some point, it will even refuse to send more requests because too many are still pending.
So make sure to end the request:
app.get('/read', isLoggedIn, function(req, res) {
dbrw.read(req.user.id, function(result) {
console.log(result);
res.end(); // or `res.send(result)`
});
});
And a tip: you should use the callback calling convertion for Node, where the first argument represents an error (if there is any) and the second argument represents the return value.

NodeJS sessions, cookies and mysql

I'm trying to build an auth system and I have app.js
var express = require('express')
, MemoryStore = require('express').session.MemoryStore
, app = express();
app.use(express.cookieParser());
app.use(express.session({ secret: 'keyboard cat', store: new MemoryStore({ reapInterval: 60000 * 10 })}));
app.use(app.router);
and the route.index as
var express = require('express')
, mysql = require('mysql')
, crypto = require('crypto')
, app = module.exports = express();
app.get('/*',function(req,res){
var url = req.url.split('/');
if (url[1] == 'favicon.ico')
return;
if (!req.session.user) {
if (url.length == 4 && url[1] == 'login') {
var connection = mysql.createConnection({
host : 'localhost',
user : 'user',
password : 'pass',
});
var result = null;
connection.connect();
connection.query('use database');
var word = url[3];
var password = crypto.createHash('md5').update(word).digest("hex");
connection.query('SELECT id,level FROM users WHERE email = "'+url[2]+'" AND password = "'+password+'"', function(err, rows, fields) {
if (err) throw err;
for (i in rows) {
result = rows[i].level;
}
req.session.user = result;
});
connection.end();
}
}
console.log(req.session.user)
when I access http://mydomain.com/login/user/pass a first time it shows in the last console call but a second time access the cookie is clean
Why do you not just use Express's session handling? if you use the express command line tool as express --sessions it will create the project template with session support. From there you can copy the session lines into your current project. There more information in How do sessions work in Express.js with Node.js? (which this looks like it may be a duplicate of)
As for sanitizing your SQL, you seem to be using the library, which will santitize your inputs for your if you use parameterized queries (ie, ? placeholders).
Final thing, you are using Express wrong (no offence). Express's router will let you split alot of your routes (along with allowing you to configure the favicon. See Unable to Change Favicon with Express.js (second answer).
Using the '/*' route will just catch all GET requests, which greatly limits what the router can do for you.
(continued from comments; putting it here for code blocks)
Now that you have an app with session support, try these two routes:
app.get('/makesession', function (req, res) {
req.session.message = 'Hello world';
res.end('Created session with message : Hello world');
});
app.get('/getsession', function (req, res) {
if (typeof req.session.message == 'undefined') {
res.end('No session');
} else {
res.end('Session message: '+req.session.message);
}
});
If you navigate in your browser to /makesession, it will set a session message and notify you that it did. Now if you navigate to /getsession, it will send you back the session message if it exists, or else it will tell you that the session does not exist.
You need to save your cookie value in the response object:
res.cookie('session', 'user', result);
http://expressjs.com/api.html#res.cookie