I'm using a node ws server built on einaros/ws.
That server has to send queries to a database. For that i'm using felixge/node-mysql.
When a user connects to the server, it should be checked if the client still exists in the database.
Here is the interesting piece of code:
console.log("client-liste ist leer");
var query = "SELECT name FROM spieler WHERE name='"+id+"' AND passwort='"+passwort+"'";
var result = queryToDatabase(query);
console.log(getTime() + "DB-Result Abfrage: " + result);
And the Code where the query is done:
var mysql = require('mysql');
var mysqlConnection = mysql.createConnection({
host: dbHost,
user: dbUser,
password: dbPassword,
});
function queryToDatabase(anfrage) {
mysqlConnection.connect();
mysqlConnection.query("USE " + db, function(err, rows, fields) {
if (err) throw err;
});
mysqlConnection.query(anfrage, function(err, rows, fields) {
if (err) throw err;
console.log("rows as String - " + JSON.stringify(rows));
return rows;
});
mysqlConnection.end();
}
The Logs in the console are:
client-liste ist leer
3.8.2012 - 15:29:0 - DB-Result Abfrage: undefined
rows as String - [{"name":"lukas"}]
Does anyone understand, why the function returns undefined?
I also tried to wait for Database-Connection to finish with a simple setTimout, but nothing changed!
You can't return a value from an asynchronous callback like the one used by query. You need to rewrite queryToDatabase so it takes a callback as its second argument and calls it with rows when the query is successful. Then your main code needs to look like:
queryToDatabase(query, function(result) {
console.log(getTime() + "DB-Result Abfrage: " + result);
});
In reality, all your code that depends on the query result will need to go into that callback.
In practice, you'd want the callback to take two arguments: an error status and a result, with the error status being null if the query was successful.
Related
SECOND EDIT
The issue was caused by the MAX_INTEGER_VALUE which is lower then the integer value I was passing. I changed the MySQL table column to TEXT instead of BIGINT and everything is being returned correctly.
Thanks for all the help!
EDIT
So I just realized that the userID variable and the guildID variables are being passed using this line of code.
mysqlModule.userCrewSearch(575783451018526744, 282997056438665217);
However the values that are being supplied to the SQL statement turn the last two digits of the number into '00'. So instead of 575783451018526744 the value being passed into the SQL statement is 575783451018526700.
So why is this value being changed when nothing I am doing in my code is changing these values?
Original Post
I'll keep this short and sweet. I'm trying to run a query using the nodejs MySQL package. I'm not sure where I'm going wrong but whenever I call my function that executes my query, I'm always returned an empty array, unless I hardcode the values into the SQL query.
Heres the code:
// Search for the User's Crew
function userCrewSearch(guildID, userID) {
pool.getConnection(function(err, connection) {
if(err) {
return console.log(err);
}
var sql = "SELECT * FROM `crew-members` WHERE `userID`=? AND `guildID`=?;";
console.log(sql);
connection.query(sql, [guildID, userID], function(err, results) {
connection.release(); // always put connection back in pool after last query
if(err) {
return console.log(err);
}
return console.log(results);
});
});
}
I'm calling this function like so: userCrewSearch(575783451018526744, 282997056438665217);
Both of the values I'm passing are integers. However this is what I get in my console.
However, here is my code with the values hardcoded into the SQL... to which the code then returns the result in the form of a RowDataPacket.
// Search for the User's Crew
function userCrewSearch(guildID, userID) {
pool.getConnection(function(err, connection) {
if(err) {
return console.log(err);
}
var sql = "SELECT * FROM `crew-members` WHERE `userID`=282997056438665217 AND `guildID`=575783451018526744;";
console.log(sql);
connection.query(sql, [guildID, userID], function(err, results) {
connection.release(); // always put connection back in pool after last query
if(err) {
return console.log(err);
}
return console.log(results);
});
});
}
Heres the result.
Bonus Question: How do I handle the RowDataPacket? Can I convert this directly into an object so I can call results.crewID and return just that value?
Same problem i was facing few days ago. I have solved this by converting the parameters into string.
function userCrewSearch(String(guildID), String(userID)) {
// your code here
}
Try adding + before your numeric parameter, it converts into number, it worked for me-
connection.query(sql, [+guildID, +userID], function(err, results) {
for your bonus questions answer, you can directly access the crewID or some other key using,
results[0].crewID
or do something like -
const [ result ] = results;
console.log(result.crewID)
I'm attempting to make two functions, one which retrives an object from an SQL database, the other which saves an object to the same SQL database. I am using node.js and mysql to do this. I have two functions, fetchEmployee and Employee.save, which fetch and save an employee respectively. When I call fetchEmployee, and the callback includes Employee.save, however, I get the error Cannot enqueue Handshake after already enqueuing a Handshake. Even weirder, Employee.save seems to run before the error is thrown.
EDIT: employee.save appearing to run is a symptom of async, as console.log("Saved!") is called before the callback function passed to SQL.parse This means the error appears during the parse. Further, if within parse console.log("connection created"); is added after con.connect, and console.log("Made it out."); is added after the end of con.connect, when calling Employee.save, the console outputs > "connection created", then throws the error, meaning the save query is never finished, but the error is thrown after con.connect
The Employee class is defined by the following
function Employee(obj) {
/** Defines the Employee class
* #arg obj.id : an integer; the employee's id
* #arg obj.name : A string; the employee's name
* #arg obj.position : A string; the employee's positions split by commas
*/
this.id = obj.id;
this.name = obj.name;
this.position = obj.position;
this.save = function() {
SQL.parse({
sql : `UPDATE EMPLOYEES
SET id=?, name=?, position=?
WHERE id=?`,
replace_ : [this.id, this.name, this.position, this.id],
result : false
});
console.log("Saved!");
}
}
Note the console.log("Saved!");, as this comes up later
fetchEmployee is defined by this function:
function fetchEmployee(id, callback) {
/** Fetch an employee from the employee table
* #arg id : An integer; the id of the employee to fetch
* #arg callback : A callback function to pass the employee to
*/
SQL.parse({ // Perform the parse, define the sql, replace, and result
sql : "SELECT * FROM employees WHERE id=?",
replace_ : [id],
result : true
},
function(err, data) {
if(err) { // Pass an error if there's an error
callback(err, null);
throw err;
}
// Pass the employee to the callback as an employee object if there's no errors
callback(null, new Employee({ // data is passed as a list from the sql table, so take only the object we need through [0]
id : data[0].id,
name : data[0].name,
position : data[0].position
})
);
});
}
Finally, SQL.parse is defined in this file:
var mySQL = require("mysql");
var con = mySQL.createConnection({ //Create connection
host : "localhost",
database : "testdb1",
user : "root",
password : "***************"
});
function parse(obj, callback) {
/** Parses an sql query.
* #arg callback : A callback function, will be passed the data
* #arg obj.sql : an sql query
* #arg obj.replace_ : A list of replacements for ?s in sql
* #arg obj.result : a boolean indicating whether a result should be returned
*/
//Assign meaningfull values
obj.replace_ = obj.replace_ || [];
callback = callback || function() {};
con.connect(function(err) {
if(err) throw err;
//Connect and pass the sql command to the server
con.query(obj.sql, obj.replace_, function(err, data) {
if(err) { //Pass the err to the callback if there is an err
callback(err, null);
throw err;
}
else if(obj.result) { // Pass the data to the callback if result is true
callback(null, data)
}
});
});
}
module.exports = {
parse : parse
};
When I call this block of code
fetchEmployee(985, function(err, data) {
if(err) throw err;
console.log(data);
data.save();
});
The console outputs
Employee {
id: 985,
name: 'Skidd',
position: 'Dishwasher, Busser',
save: [Function] }
Saved!
Error: Cannot enqueue Handshake after already enqueuing a Handshake. [...]
It appears to me that it correctly runs fetchEmployee, as data is logged to the console correctly with the data of the employee. It then logs Saved!, seeming to indicate that Employee.save ran correctly, then after all the code is done, throws the error. I can't for the life of me figure out why this would happen, here or on google or through testing.
I've tried to add con.end to the end of parse in sql.js, this changes the error to Cannot enqueue Handshake after invoking quit
I was able to solve this problem by placing
var con = mySQL.createConnection({ //Create connection
host : "localhost",
database : "testdb1",
user : "root",
password : "***************"
});
inside of the parse function, though I'm not 100% sure why this worked.
I followed what the previous person did and it worked for me too.
I guess the problem was the connection was being made asynchronously.
putting this inside the promise solved the problem
I am weighting a node.js application, the result I get from my mysql query is,
[ RowDataPacket { name: 'ubuntu' } ]
(Ubuntu is the only thing in the row)
What I would like to do is shorten my variable, "results" so that it equals ubuntu for example, or just every thing between the '', I am new to JS. I am using the standard way of querying the sql database,
It is being done as so:
var mysql = require('mysql');
var connection = mysql.createConnection({
host : 'localhost',
user : 'root', //just using root for my personal testing.
password : 'root',
database : 'Sonic'
});
connection.connect();
var connect = connection.query( 'SELECT name FROM Sonic_url',
function(err, fields, results, rows) {
// if (results === input) {
var sqldata = results.substring(1, 4);
console.log(results);
if (err) throw err;
// console.log('I belive we have found what you are after, is: ' + input + ' ' + 'what you are after?');
//}
});
I would like to be able to do a basic IF with the variable input and a variable from the mysql query, so I can print to screen if the result was found or not.
The correct signature for the mysql query is:
connection.query(query, function (error, results, fields) {
// error will be an Error if one occurred during the query
// results will contain the results of the query
// fields will contain information about the returned results fields (if any)
});
What you want is to log the value of name. If your query produces one result, you can access this value from the first item in the rows array:
connection.query('SELECT name FROM Sonic_url', function(err, rows, fields) {
console.log(rows[0].name);
});
Ive written and basic Node app (my first) to insert many csv rows into mongo (items array in the code below). Once all items have been inserted the db connection should be closed and the program exited.
The issue ive been working with is figuring out when to close the db connection once all inserts have returned a result. Ive gotten it working by counting all of the insert result callbacks but to me this feels clunky. I know one improvement I could make is to batch the inserts via an array to the insert function but ill still need to have my code be aware of when all inserts have completed (assuming it would be bad to insert 100k items in one query). Is there and better way (my code feels hacky) to do this?
Hack part...
function (err, result) {
queryCompletedCount++;
if (err) console.log(err);
//Not sure about doing it this way
//Close db once all queries have returned a result
if (queryCompletedCount === items.length) {
db.close();
console.log("Finish inserting data: " + new Date());
}
}
Full insert code
MongoClient.connect(dbConnectionURL, function (err, db) {
if (err) {
console.log("Error connecting to DB: " + err);
} else {
var productCollection = db.collection('products');
console.log("Connected to DB");
console.log("Start inserting data: " + new Date());
var queryCompletedCount = 0;
for (var i = 0; i < items.length; i++) {
productCollection.insert([{
manufacturerCode: null,
name: items[i].name,
description: null
}], function (err, result) {
queryCompletedCount++;
if (err) console.log(err);
//Not sure about doing it this way
//Close db once all queries have returned a result
if (queryCompletedCount === items.length) {
db.close();
console.log("Finish inserting data: " + new Date());
}
});
}
}
});
What do you think about realizing this issue with async module like this:
async = require('async')
async.eachSeries(items, function (item, next) {
productCollection.insert(productCollection.insert(
[{
manufacturerCode: null,
name: item.name,
description: null
}], function (err, result) {
if (err) {
return next(err);
}
next();
})
)
}, function () {
// this will be called after all insertion completed
db.close();
console.log("Finish inserting data: " + new Date());
});
What you need here is MongoDB's Write Concern, configured in the strictest way.
There are two levels of Write Concern. The first is the write mode, in which case the query returns only if the result is written to the configured number of mongo instances. In your case I suppose there is a single instance, but for future you may configure it as "w": "majority". The second level is the Journal concern, where by setting "j": 1 your query will return only when the data is written into the journal.
So in your case you best Write Concern configuration might be {"w": "majority", "j": 1}. Just add it as the last argument of your insert statement.
All I want to do is insert some data if my database doesn't have that, so I put Insert SQL into my callback function of my Select SQL, but I got error like this:
{ [Error: Cannot enqueue Query after invoking quit.] code: 'PROTOCOL_ENQUEUE_AFTER_QUIT', fatal: false }
my code snippet is here:
db.query('SELECT count(*) as Resultcount FROM tablename WHERE email = ? and password = ?', [post.email, post.password], function(error, result){
if (result[0].Resultcount == 0){
var query2 = db.query('INSERT INTO tablename SET ?', [post], function(err, result) {
if(err){
console.log(err);
}
console.log(result);
});
}
else{
console.log('have data already');
}
});
Could someone give me some advice?
Thanks
----update----
actually, the callback function of select SQL is not an anonymous function, my code snippet about db.end() is like this:
var QueryResults = new queryResultFuntion(Back_results);
db.query('SELECT count(*) as Resultcount FROM tablename WHERE email = ? and password = ?', [post.email, post.password], QueryResults.queryResult );
db.end();
You db.end() call will queue the connection to close once the SELECT has completed, so when you attempt to do the inner INSERT query, the database connection will have been closed, hence the error PROTOCOL_ENQUEUE_AFTER_QUIT, as you are attempting to queue a new command after the connection is closed.
Depending on how you are creating the connection, you should either move your db.end() call inside the callbacks, or not have a db.end() call at all if the connection is opened on program start.