Use NodeJS to run an SQL file in MySQL - 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 }}

Related

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

connecting to MySQL async using nodeJs and 'Q'

I'm dealing with project using Postgres DB, it uses nodeJs and 'Q' framework. I want to replace postgres DB with mysql database, since I'm a total newbie to nodeJs, I have no idea on how to idea? It will be great if you could share an example of mysql connect and if possible a simple query using nodeJs and 'Q'.
Take a look at this answer. It seems to answer your question.
Taken exactly from the the answer:
var mysql = require('mysql');
var Q = require('Q');
var connection = mysql.createConnection({
host : 'localhost',
user : 'root',
password : ''
});
connection.connect();
function doQuery1(){
var defered = Q.defer();
connection.query('SELECT 1 AS solution',defered.makeNodeResolver());
return defered.promise;
}
function doQuery2(){
var defered = Q.defer();
connection.query('SELECT 2 AS solution',defered.makeNodeResolver());
return defered.promise;
}
Q.all([doQuery1(),doQuery2()]).then(function(results){
res.send(JSON.stringify(results[0][0][0].solution+results[1][0][0].solution));
});
connection.end();
However, if you don't need to make multiple calls at once, you can skip the use of Q.all and just do something like:
return doQuery1().then(function(res){
console.log(res);
connection.end();
});
Thanks, this is how i ended up doing it in the end:
var connection = mysql.createConnection({host : 'host',user :'user', password : 'pass', database : 'db'});
var connect = Q.denodeify(connection.connect.bind(connection));
connect().then(function (values) {
console.log('...connected to database');
var query = Q.denodeify(connection.query.bind(connection));
})

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

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.