Trying to query my database and each time I do, it runs all the queries at the end instead of when I need them in nodejs.
var mysql = require('mysql');
var con = mysql.createConnection({
host: database.host,
user: database.user,
password: database.password,
database: database.database
});
The connection data I am pulling from a json file.
function getSymbol(id){
var s = "";
con.query("SELECT * FROM Symbol WHERE PlayerID = '" + id + "'", function (err, result, fields) {
if (err) throw err;
console.log(result);
if (result.length < 1) {
console.log(result);
s = result[0].Symbol;
}
else {
s = "!";
}
});
console.log(s);
return s;
}
It all runs at the end of the program wondering if there is a fix or if I should switch to python (seriously considering rewriting all of it at this point).
The problem is what you have written comes under NIO and it wont wait for executing the next statement unless you ask it to. Try the below code:
async function getSymbol(id){
var s = "";
try {
let result = await con.query("SELECT * FROM Symbol WHERE PlayerID = '" + id + "'")
if (result.length < 1) {
console.log(result);
s = result[0].Symbol;
}
else {
s = "!";
}
}catch(error){
console.log(error);
throw new error;
}
console.log(s);
return s;
}
Note: I have used async/await. You can also use Promises
As mentioned, the method is NOT sync. Your result will be on the callback you pass.
con.query(sql, function (err, result) {
if (err) throw err;
console.log("The Data: " + result);
});
More Info: https://www.w3schools.com/nodejs/nodejs_mysql.asp
Moreover, you need to connect first with con.connect( <callback-here> ).
The best way to work with this is to avoid the callbacks for async/wait syntax.
Related
I have been struggling for a few days with a problem that seems simple to me. I want to insert a value if it does not exist in a mysql database with nodejs.
I have an array of array, and I need to loop inside a child to check every data.
Example of data
finalRow = [['a > 'b'], ['a' > 'c']];
My code
for(let i=0; i < finalRow.length-1; i++) {
var splitcat = finalRow[i].split(' > ');
(async function(){
for(let j=0; splitcat.length-1; j++) {
var query = "SELECT * from category where name = '" + splitcat[j] + "'";
await con.query(query, async function (err, result, fields) {
if (err) throw err;
if(result && result.length) {
console.log("nothing");
} else {
console.log("insert into db");
await con.query(`INSERT INTO category (name, url, description, parent_id) VALUES (?, ?, ?, ?)`,
[splitcat[j], '', '', null], function (err, result) {
if (err) throw err;
});
}
});
}
})();
I tried several versions of this code, but
the loop does not wait for the existence check and inserts all the data.
Thanks for your help
I'm new to learning Node.js, so I'm still getting used to asynchronous programming and callbacks. I'm trying to insert a record into a MS SQL Server database and return the new row's ID to my view.
The mssql query is working correctly when printed to console.log. My problem is not knowing how to properly return the data.
Here is my mssql query - in addJob.js:
var config = require('../../db/config');
async function addJob(title) {
var sql = require('mssql');
const pool = new sql.ConnectionPool(config);
var conn = pool;
let sqlResult = '';
let jobID = '';
conn.connect().then(function () {
var req = new sql.Request(conn);
req.query(`INSERT INTO Jobs (Title, ActiveJD) VALUES ('${title}', 0) ; SELECT ##IDENTITY AS JobID`).then(function (result) {
jobID = result['recordset'][0]['JobID'];
conn.close();
//This prints the correct value
console.log('jobID: ' + jobID);
}).catch(function (err) {
console.log('Unable to add job: ' + err);
conn.close();
});
}).catch(function (err) {
console.log('Unable to connect to SQL: ' + err);
});
// This prints a blank
console.log('jobID second test: ' + jobID)
return jobID;
}
module.exports = addJob;
This is my front end where a modal box is taking in a string and passing it to the above query. I want it to then receive the query's returned value and redirect to another page.
// ADD NEW JOB
$("#navButton_new").on(ace.click_event, function() {
bootbox.prompt("New Job Title", function(result) {
if (result != null) {
var job = {};
job.title = result;
$.ajax({
type: 'POST',
data: JSON.stringify(job),
contentType: 'application/json',
url: 'jds/addJob',
success: function(data) {
// this just prints that data is an object. Is that because I'm returning a promise? How would I unpack that here?
console.log('in success:' + data);
// I want to use the returned value here for a page redirect
//window.location.href = "jds/edit/?jobID=" + data;
return false;
},
error: function(err){
console.log('Unable to add job: ' + err);
}
});
} else {
}
});
});
And finally here is the express router code calling the function:
const express = require('express');
//....
const app = express();
//....
app.post('/jds/addJob', function(req, res){
let dataJSON = JSON.stringify(req.body)
let parsedData = JSON.parse(dataJSON);
const addJob = require("../models/jds/addJob");
let statusResult = addJob(parsedData.title);
statusResult.then(result => {
res.send(req.body);
});
});
I've been reading up on promises and trying to figure out what needs to change here, but I'm having no luck. Can anyone provide any tips?
You need to actually return a value from your function for things to work. Due to having nested Promises you need a couple returns here. One of the core features of promises is if you return a Promise it participates in the calling Promise chain.
So change the following lines
jobID = result['recordset'][0]['JobID'];
to
return result['recordset'][0]['JobID']
and
req.query(`INSERT INTO Jobs (Title, ActiveJD) VALUES ('${title}', 0) ; SELECT ##IDENTITY AS JobID`).then(function (result) {
to
return req.query(`INSERT INTO Jobs (Title, ActiveJD) VALUES ('${title}', 0) ; SELECT ##IDENTITY AS JobID`).then(function (result) {
and
conn.connect().then(function () {
to
return conn.connect().then(function () {
You may need to move code around that is now after the return. You would also be well served moving conn.close() into a single .finally on the end of the connect chain.
I recommend writing a test that you can use to play around with things until you get it right.
const jobId = await addJob(...)
console.log(jobId)
Alternatively rewrite the code to use await instead of .then() calls.
so here's the issue, everything inside the con.query(query, function (err, result, fields) is never called. So this is the part of code that is about verifying that when the user is signing up, the email that he took is not already taken. argv[0] contains the email that the user typed (it's not wrong, I debugged it). So I obviously created two accounts with the same email but the second one is never flagged (the function is continuing instead of returning "userexists").
var mysql = require('mysql');
var con = mysql.createConnection(Credentials). // 👈 The connection is established, it's not a problem.
var query = "SELECT id FROM accounts_data WHERE email = '" + argv[0] + "'";
var r;
con.query(query, function (err, result, fields) {
if (err)
return "failed";
if(result != undefined)
return "userexists" // The if is never checked
});
Thank you.
EDIT:
Hello everyone, so the console.log(results.length) is printing the right result, but how can I give the result to r? Because the last console.log(r) is still printing 0.
var r = 0;
var sql = 'SELECT * FROM accounts_data WHERE email = ' + con.escape(argv[0]);
con.query(sql, function (error, results, fields) {
if (error) throw error;
console.log(results.length); // Right result
r = results.length; // Not giving the result to r
});
console.log(r); // Not the right result
Try using Promise's, they'll help get away from 'callback-hell'
const userExists = async emailAddress => new Promise((resolve, reject) => {
con.query(`
SELECT EXISTS(
SELECT id FROM accounts_data WHERE email = ?
);
`,
[emailAddress],
(err, result) => {
if (err) { reject(err); }
resolve(result);
}
)
);
await userExists('abc#example.com') // => boolean
I'm trying to generate a hashchain using the following code:
var async = require('async');
var _ = require('lodash');
var offset = 1e7;
var games = 1e7;
var game = games;
var serverSeed = '238asd1231hdsad123nds7a182312nbds1';
function loop(cb) {
var parallel = Math.min(game, 1000);
var inserts = _.range(parallel).map(function() {
return function(cb) {
serverSeed = genGameHash(serverSeed);
game--;
query('INSERT INTO `hash` SET `hash` = ' + pool.escape(serverSeed));
};
});
async.parallel(inserts, function(err) {
if (err) throw err;
// Clear the current line and move to the beginning.
var pct = 100 * (games - game) / games;
console.log('PROGRESS: ' + pct.toFixed(2) + '%')
if (game > 0){
loop(cb);
}else {
console.log('Done');
cb();
}
});
}
loop(function() {
console.log('Finished with SEED: ', serverSeed);
});
When I run this code it generates a hash chain of 1k hash's, while I'm trying to generate a chain of 1m hash's. It seems like async isn't working properly, but I have no idea why, there are no errors in console, nothing that points out a flaw.
Any ideas?
Do you can run it with smaller games (about 3000)?
Your parallel function nerver send done signal because the callback of inserts item never trigged. I think query function has two pramasters query(sql: string, callback?: (err, result) => void) (Typescript style).
I suggest you change your logic and flow like below block code:
var inserts = _.range(parallel).map(function() {
return function(cb) {
serverSeed = genGameHash(serverSeed);
query('INSERT INTO `hash` SET `hash` = ' + pool.escape(serverSeed), function(err, result) {
if(result && !err) {
game--;
}
cb(); // remember call the callback
});
};
});
In your code, you have used async.parallel, I think it is not good idea, too many connection has be open(1m). Recommeded for this case is parallelLimit
I'm trying to create a NodeJS application to pull SQL records and insert them into MongoDB. The tables I'm interested in are somewhat large (1million+ records). For small datasets (< 200,000) my app works great, but running against the full table starts to eat up RAM and bring the server to a crawl.
It looks like Node is running through my "for" loop, branching off processes for each SQL sub select, and then running the MongoDB updates.
I never see "Mongo Connected!" until the last "Getting Responses for Activity #" is written to the screen.
#!/var/node/bin/node
var odbc = require("odbc");
var db = new odbc.Database();
var MongoClient = require('mongodb').MongoClient;
var format = require('util').format;
db.open("DSN=<DSN>;SERVER=<SERVER>;DATABASE=<DB>;UID=<UID>;PWD=<PWD>", function (err) {
if(err) throw err;
console.log("SQL Connected!");
var sqlstr = "SELECT TOP 1000 * FROM tbl_A NOLOCK";
console.log("Executing '" + sqlstr + "' against SQL Server");
db.query(sqlstr, function (sql1err, rows, moreResults) {
if (sql1err) throw sql1err;
for (var i = 0; i < rows.length; i++) {
InsertActivity(db, rows[i], i, rows.length, function () {});
}
});
});
function InsertActivity(sql, activity, cur, total, callback) {
console.log("Getting Responses for Activity #" + activity.ActivityID);
var rsql = "SELECT * FROM tbl_Responses NOLOCK WHERE ActivityID = " + activity.ActivityID;
sql.query(rsql, function (sqlerr, rows, moreResults) {
if (sqlerr) console.log(sqlerr);
activity.resonses = rows;
MongoClient.connect('mongodb://localhost:27017/m', function (merr, mdb) {
console.log("Mongo Connected!");
mdb.collection("activity").insert(activity, function () {
console.log("Inserted Activity #" + activity.ActivityID + " inserted into Mongo");
mdb.close(function () { console.log("Mongo Disconnected!"); });
callback();
});
});
if (cur == total - 1) sql.close(function () { console.log("SQL Disconnected!"); });
});
console.log(rsql);
}
What you need is unfortunately an undocumented function (I'll fix that). The function is db.queryResult which returns the result object that allows you to fetch rows individually. That will avoid buffering the entire result set into memory.
https://github.com/wankdanker/node-odbc/blob/master/test/test-query-select-fetch.js
var db = require('odbc')();
db.open(connectionString, function (err) {
db.queryResult('select * from tbl_A NOLOCK', function (err, result) {
fetchMore();
function fetchMore() {
result.fetch(function (err, data) {
if (!data) {
//we're all done, clean up
}
doStuffWithData(data, function (err) {
fetchMore();
});
});
}
});
});
function doStuffWithData(data, cb) {
//do stuff
cb(null);
}