NodeJS - How to pass a mysql connection from main to child process? - mysql

I tried the following server+worker code but it simply did not work.
server.js:
var net = require('net');
var mysql = require('mysql');
var cp = require('child_process');
var serverPort=20460;
var connection = mysql.createConnection({
database : 'test',
host : 'localhost',
user : 'root',
password : ''
});
var server = net.createServer(function (socket){
socket.on('data',function(data){
console.log("Server received: ",data);
var child = cp.fork('./worker');
child.send({'connection': connection});
});
});
connection.connect(function(err, two){
if (!err) {
server.listen(serverPort);
}
});
worker.js:
process.on('message', function(obj) {
//Will add more code to it later...
console.log("CHILD::Received: ",obj);
});
Gives me the following error at the child process' console.log():
JSON.stringify, avoid TypeError: Converting circular structure to JSON
Any suggestions ?

The way I'd do it is to have worker.js be the real "app" and the server.js just sets up the clustering. I've not tested this, but something along the lines of this:
// worker.js
var connection = require('./db');
var net = require('net');
var server = net.createServer(function (socket){
socket.on('data',function(data){
console.log("Server received: ",data);
connection.connect();
connection.query(/* your query here for inserting data */);
connection.end();
});
});
// db.js
var mysql = require('mysql');
var serverPort=20460;
var connection = mysql.createConnection({
database : 'test',
host : 'localhost',
user : 'root',
password : ''
});
module.exports = connection;
// server.js
var cluster = require('cluster');
var numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
// Fork workers.
for (var i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', function(worker, code, signal) {
console.log('worker ' + worker.process.pid + ' died');
});
} else {
require('./worker');
}
For bonus points, you could use something like node-pool to create a connection pool, and have the db module return a connection from the pool instead.

Related

Nodejs Expess Script Unable to Create the Mysql Database Table

I created node js express applications with express generator. I am trying to create table by executing database script called db.js . This script is located into database folder . I am able to run the server but when I tried to execute the script by using C:\Users\Khundokar Nirjor\Desktop\Nodejs Resources\shopping-cart\database>node db.js
C:\Users\Khundokar Nirjor\Desktop\Nodejs Resources\shopping-cart\database>
It is not able to create the table or inserting records.
Here is my app.js code .
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var expressHbs = require('express-handlebars');
var mysql = require('./database/db');
var app = express();
require('./database/db');
// view engine setup
app.engine('.hbs',expressHbs({defaultLayout: 'layout' , extname: '.hbs'}));
app.set('view engine', '.hbs');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', indexRouter);
//app.use('/users', usersRouter);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
Here is the db.js code .
var mysql = require('mysql');
//var app = express();
var con = mysql.createConnection({
host: "localhost",
user: "root",
password: "",
database: "shopdb"
});
con.connect(function(err) {
if (err) throw err;
console.log("Connected!");
var sql = "CREATE TABLE products (imagepath VARCHAR(255), tittle VARCHAR(255), descriptions VARCHAR(255),price VARCHAR(255))";
var sql1 = "INSERT INTO products (imagepath, tittle,descriptions,price) VALUES ?";
var values = [
['https://upload.wikimedia.org/wikipedia/en/5/5e/Gothiccover.png', 'Gothic Veido Game','Awesome Game !!!!','25'],
['https://upload.wikimedia.org/wikipedia/en/5/5e/Gothiccover.png', 'Gothic Veido Game','Awesome Game old !!!!','100'],
['https://upload.wikimedia.org/wikipedia/en/5/5e/Gothiccover.png', 'Gothic Veido Game','Awesome Game New !!!!','120'],
['https://upload.wikimedia.org/wikipedia/en/5/5e/Gothiccover.png', 'Gothic Veido Game','Awesome Game !!!!','26'],
];
con.query(sql, sql1,[values], function (err, result) {
if (err) throw err;
console.log("Number of records inserted: " + result.affectedRows);
});
});
con.destroy();
You should enable multistatement true while creating a connection as you are running multiple statements.change your configuration options as below:
var con = mysql.createConnection({
host: "localhost",
user: "root",
password: "",
database: "shopdb",
multipleStatements: true
});
Refer this :
https://github.com/mysqljs/mysql#multiple-statement-queries

Unable to Update MySQL (AWS RDS) table from Lambda though i am able to connect and INSERT

Below is my lambda function. A request is coming from API (API Gateway). Even when I tried to pass the values directly to update table, its not updating.
I am able to INSERT data into the same table through API. Just wondering what's wrong here.
Appreciate any help. Thanks in advance.
var mysql = require('mysql');
var config = require('./config.json');
var sql,response;
exports.handler = function(event, context) {
var connection = mysql.createConnection({
host : config.dbhost,
user : config.dbuser,
password : config.dbpassword,
database : config.dbname
});
exports.handler = function(event, context,callback) {
//prevent timeout from waiting event loop
context.callbackWaitsForEmptyEventLoop = false;
var variable1= event.variable1;
var variable2= event.variable2;
var id= event.id;
connection.query('UPDATE LocationData SET latitude = ?,longitude =? WHERE userId = ?', [variable1, variable2,id], function(error, results, fields) {
response = {};
response['id'] = results.id;
response['variable1'] = results.variable1;
response['variable2'] = results.variable2;
context.succeed(response);
});
};
};
You are missing the call to the connect function. A working example would look like this:
var mysql = require('mysql');
var config = require('./config.json');
exports.handler = function(event, context) {
var connection = mysql.createConnection({
host : config.dbhost,
user : config.dbuser,
password : config.dbpassword,
database : config.dbname
});
connection.connect(); // <--- MISSING THIS!
exports.handler = function(event, context,callback) {
context.callbackWaitsForEmptyEventLoop = false;
var variable1 = event.variable1;
var variable2 = event.variable2;
var id = event.id;
var sql = 'UPDATE LocationData SET variable1=?,variable2=? WHERE userId=?';
connection.query(sql, [variable1, variable2, id], function(error, results, fields) {
context.succeed({
id: results.id,
variable1: results.variable1,
variable2: results.variable2
});
});
};
};
Also, as a general advice, you should always check the error variable in the callback, in case something is going wrong, and react accordingly to it.

Connecting to database in Node.js from routes

I'm working on a express server and am having trouble accessing my database from a route file I have set up for users. When I attempt to make a get request I receive this as an error.
"code": "ER_NO_DB_ERROR",
"errno": 1046,
"sqlState": "3D000",
"index": 0
I have been trying to look for a solution online but most of the answers suggest requiring db.js file everywhere which I already do. I have a feeling I need to pass the connection I made in app.js around but I am not sure how to do this. The relevant parts of my files are below. Database login info has been redacted, I do get a successful connection in app.js. I'm fairly new to this so any help would be appreciated, specifically if there is a better way to use the pool implemented in db.js.
app.js
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var index = require('./routes/index');
var users = require('./routes/users');
var mysql = require('mysql')
var app = express();
var users = require('./routes/users');
var media = require('./routes/media');
var tv = require('./routes/tv');
var movies = require('./routes/movies');
var db = require('./db.js')
var connection = mysql.createConnection({
port: '3306',
host: '*********************',
user: '********',
password: '******'
})
db.connect(function(err) {
if (err) {
console.log('Unable to connect to MySQL.')
process.exit(1)
} else {
console.log('Successfully connected')
}
})
app.use('/api', users);
models/user.js
var db = require('../db.js');
var passwordHash = require('password-hash');
exports.getAll = function(done) {
db.get().query('SELECT * FROM users', function (err, rows) {
if (err) return done(err)
done(null, rows)
})
}
routes/users.js
var express = require('express');
var router = express.Router()
var user = require('../models/user');
var db = require('../db.js');
//this doesn't prInt anything currently. This is prompting me to believe I somehow
//need to pass a connection object or am using the pool properly.
console.log(db.get());
router.route('/users').get(function(req, res) {
user.getAll(function(err, users) {
if (err) {
return res.send(err);
}
res.json(users);
});
});
db.js
//this is taken mostly from a tutorial I found online
var mysql = require('mysql')
, async = require('async')
var PRODUCTION_DB = 'app_prod_database'
, TEST_DB = 'app_test_database'
exports.MODE_TEST = 'mode_test'
exports.MODE_PRODUCTION = 'mode_production'
var state = {
pool: null,
//mode: null,
}
exports.connect = function(done) {
state.pool = mysql.createPool({
port: '3306',
host: '***************',
user: '*********',
password: '*******'
//database: mode === exports.MODE_PRODUCTION ? PRODUCTION_DB : TEST_DB
})
//state.mode = mode
done()
}
exports.get = function() {
return state.pool
}
exports.fixtures = function(data) {
var pool = state.pool
if (!pool) return done(new Error('Missing database connection.'))
var names = Object.keys(data.tables)
async.each(names, function(name, cb) {
async.each(data.tables[name], function(row, cb) {
var keys = Object.keys(row)
, values = keys.map(function(key) { return "'" + row[key] + "'" })
pool.query('INSERT INTO ' + name + ' (' + keys.join(',') + ') VALUES (' + values.join(',') + ')', cb)
}, cb)
}, done)
}
exports.drop = function(tables, done) {
var pool = state.pool
if (!pool) return done(new Error('Missing database connection.'))
async.each(tables, function(name, cb) {
pool.query('DELETE * FROM ' + name, cb)
}, done)
}
Either supply a valid database in the createConnection...
var connection = mysql.createConnection({
port: '3306',
host: '*********************',
user: '********',
password: '******',
database: 'mydatabase'
And/or, qualify the table name with the name of the database in the query:
db.get().query('SELECT * FROM mydatabase.users',
^^^^^^^^^^^
What it looks like is happening in the current code, a connection is established to the MySQL Server. But no USE mydatabase statement has been executed. When the SQL statement SELECT ... FROM users is executed, MySQL doesn't know which database the users is supposed to reference. (That table could exist in multiple databases containing a table or view named users.)
That's what's causing the 1046 No database selected error.

connect nodejs to mysql

I have following code that connect nodejs to mysql. When I run it the first time it work the data print out to the page but when I refresh the page it tell 'This site can’t be reached' 'localhost refused to connect.' I don't understand why I can connect to server only the first time. I use url as localhost:3000/car
var express = require('express');
var app = express();
app.use(express.static(__dirname));
var mysql = require('mysql');
var connection = mysql.createConnection({
host : 'localhost',
user : 'joeM',
password : 'versus',
database : 'joe'
});
app.get('/car', function(req, res){
connection.connect();
connection.query('SELECT * FROM test1', function(err, rows, fields) {
if (err) throw err;
var print = '<ol>';
for( var i = 0; i<rows.length; i++){
print +=('<li>ID:' + rows[i].id + ' Brand:' + rows[i].brand +'</li>' );
}
print += '</ol>';
res.send(print);
connection.end();
});
});
app.listen(3000, function(){
console.log('Magic Happen at port: 3000');
});
dont use connection.connect(); in every request and set it out of request block

Use NodeJS to run an SQL file in MySQL

I am using the mysql plugin for nodejs and it is fantastic at doing everything I need so far.
However I have come across a stumbling block. I have created a MySQL provider that exports a mysql pool:
var mysql = require('mysql');
var mysqlPool = mysql.createPool({
host : '127.0.0.1',
user : 'root',
password : ''
});
mysqlPool.getConnection(function(err, connection) {
connection.query("INSERT INTO ....
I can select, create, insert, etc all fine, but I've come across a task where I would like to run a small SQL string with about 10 different commands together. I've thought about doing one of the following:
Execute a SQL file against a database using mysql
Run a query and enable multipleStatements
I have written some code to execute mysql as a child process, but I would really love to avoid doing this:
var cp = require("child_process");
var cmdLine = "mysql --user=autobuild --password=something newdb < load.sql";
cp.exec(cmdLine, function(error,stdout,stderr) {
console.log(error,stdout,stderr);
});
The problem with option two is I would rather not enable multipleStatements for every query, just this one particular one. I have thought about creating a new connection, but just thinking of other ways this could be done.
TL;DR?
Using NodeJS and MySQL how can I execute the following into a database:
CREATE TABLE pet (name VARCHAR(20), owner VARCHAR(20) );
CREATE TABLE sofa (name VARCHAR(20), owner VARCHAR(20) );
CREATE TABLE table (name VARCHAR(20), owner VARCHAR(20) );
Thanks so much for anyone who shares their ideas
You can use the connection option called multipleStatements:
// Works with the pool too.
var connection = mysql.createConnection({multipleStatements: true});
Then, you can pass the queries like these:
connection.query('CREATE 1; CREATE 2; SELECT 3;', function(err, results) {
if (err) throw err;
// `results` is an array with one element for every statement in the query:
console.log(results[0]); // [create1]
console.log(results[1]); // [create2]
console.log(results[2]); // [select3]
});
Here is a big .sql file friendly way to progmatically execute multiple queries against MySQL without using the multipleStatements property and a massive buffer. Please note this is not the most efficient way to upload to mysql.
var mysql = require('mysql');
var fs = require('fs');
var readline = require('readline');
var myCon = mysql.createConnection({
host: 'localhost',
port: '3306',
database: '',
user: '',
password: ''
});
var rl = readline.createInterface({
input: fs.createReadStream('./myFile.sql'),
terminal: false
});
rl.on('line', function(chunk){
myCon.query(chunk.toString('ascii'), function(err, sets, fields){
if(err) console.log(err);
});
});
rl.on('close', function(){
console.log("finished");
myCon.end();
});
Looks like there is a module for this purpose: execsql
This will do the trick:
var express = require("express");
var bodyParser = require("body-parser");
var mysql = require('mysql');
var fs = require('fs');
var app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(express.static(__dirname));
var defaultConnection = mysql.createConnection({
host : 'localhost',
user : 'root',
password : '',
database: 'utpDatabase'
});
function dbCall_file (endpoint, operation, settings, filename){
app.post(endpoint, function(request, response){
var data = request.body;
var path = 'path/to/queries/' + filename
var connection = (settings == 'default') ? defaultConnection : settings;
var callback = function(arg){
var query = arg.replace(/{{[ ]{0,2}([a-zA-Z0-9\.\_\-]*)[ ]{0,2}}}/g, function(str, mch){ return data[mch]});
connection.query(query, function(err, rows){
if (!err){
var toClient = (operation == 'select') ? rows : {success: true};
response.send(toClient);
} else {
console.log(err);
response.send({error: err, query: query});
}
});
};
fs.readFile(path, 'utf8', function(err, data){
if (!err){
callback(data);
} else {
callback(err);
}
});
});
};
Then in your .sql file wrap your node variables in double curlies- for example, if you want to query first names for node variable data.firstName from your post call:
SELECT * FROM users WHERE name={{ firstName }}