Node.js and mysql Callback : query in query callback - javascript

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.

Related

Socket.io, Node.js: How can a javascript variable be passed to mysql query from in a javascript.js?

Socket.io, Node.js: How can a javascript variable be passed to mysql query from in a javascript.js?
There is an error when a variable of value '222.222.222.222', is attempted to be passed into the mysql query, but not when a variable having a value of '2' is passed into the same mysql query.
Any help would be greatly appreciated.
This gives error:
var javascriptVariable = '222.222.222.222';
$query = 'INSERT INTO misc_table (misc_field) VALUES ('+javascriptVariable+')';
connection.query($query, function(err, rows, fields) {
if(err){
console.log("An error ocurred performing the query.");
return;
}
console.log("Query succesfully executed: ", rows);
});
This does not give error:
var javascriptVariable = '2';
$query = 'INSERT INTO misc_table (misc_field) VALUES ('+javascriptVariable+')';
connection.query($query, function(err, rows, fields) {
if(err){
console.log("An error ocurred performing the query.");
return;
}
console.log("Query succesfully executed: ", rows);
});
Never ever thought to update databases in this manner.
First. In fact, you try to execute next code
INSERT INTO misc_table (misc_field) VALUES (222.222.222.222)
Second. This is the straight way to sql injection
Thrid. Try something like this
var javascriptVariable = '222.222.222.222';
let $query = 'INSERT INTO misc_table (misc_field) VALUES (?)';
connection.query(
$query,[ javascriptVariable ],
function (...args) {
....
}
);

NodeJs + Mysql Multi Query with chain method

Hi friends I have to ask the mysql query repeatedly in my application with Node js. I will shape the second interrogation according to the result of the first interrogation. The following code example does not work. Can you help me? You can support the functioning of the queries do not hang.
let sql = "SELECT COUNT(*) AS miktar FROM orders";
connection.query(sql, function(err, result) {
if (err) throw err;
let sqlAnother =
"SELECT COUNT(*) AS miktar FROM orders WHERE result=" +
result[0].miktar +
"";
connection.query(sqlAnother, function(err, result) {
if (err) throw err;
callback(result);
});
});
connection.end();
You can do this in one call with a subquery:
SELECT COUNT(*) AS miktar FROM orders WHERE result = (SELECT COUNT(*) FROM orders)
If this returns a result in the MySQL CLI, then your code must provide this result to callback. Otherwise it's just that no row in orders happens to have a field result that contains the exact amount of rows in the table.

node.js + mysql: "Cannot enqueue Handshake after already enqueuing a Handshake."

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

How to insert in two tables in one time? prepared statements

How to insert two table in one time?
I need to insert second table user_information the field user_id with first table user insert returning id, I found this answer but I can't find how to be with params prepared statements
var dbQuery = 'WITH insertUser AS (
INSERT INTO "user" (status, create_date) VALUES ($1, $2) RETURNING id
)
, insertUserInformation AS (
INSERT INTO user_information (user_id, email) VALUES ($3, $4)
)
';
yield queryPromise(dbClient, dbQuery, [status, timestamp, ??, email]);
pg
Use transactions. That way either all queries will be committed, or none will be committed. And the incomplete state before you have executed all queries is not visible for other processes.
More on how to do transactions in node-postgres is available at https://github.com/brianc/node-postgres/wiki/Transactions
And for reference the most relevant section is:
var Client = require('pg').Client;
var client = new Client(/*your connection info goes here*/);
client.connect();
var rollback = function(client) {
//terminating a client connection will
//automatically rollback any uncommitted transactions
//so while it's not technically mandatory to call
//ROLLBACK it is cleaner and more correct
client.query('ROLLBACK', function() {
client.end();
});
};
client.query('BEGIN', function(err, result) {
if(err) return rollback(client);
client.query('INSERT INTO account(money) VALUES(100) WHERE id = $1', [1], function(err, result) {
if(err) return rollback(client);
client.query('INSERT INTO account(money) VALUES(-100) WHERE id = $1', [2], function(err, result) {
if(err) return rollback(client);
//disconnect after successful commit
client.query('COMMIT', client.end.bind(client));
});
});
});
It's impossible in postgresql. I solved exact the same problem by creating function and simply executing with parameters. As I see in your table structure, you don't have many attributes, so this will be relatively easy.
Example code:
function.sql
CREATE OR REPLACE FUNCTION createSomething
(
IN attr1 VARCHAR(20),
IN attr2 VARCHAR(200)
)
RETURNS void AS $$
DECLARE userId INTEGER;
BEGIN
INSERT INTO table1 (col1, col2) VALUES
(
attr1,
attr2
) RETURNING id INTO userId;
INSERT INTO table2 (user_id, col11, col2) VALUES
(
userId,
col11,
col12
);
END;
$$ LANGUAGE plpgsql;
Usage:
SELECT createSomething('value1', 'value2');
Please notice, that second insert statement will know what was recently user's id and will use it.
PostgreSQL Prepared Statements will not let you do it. You will have to use a transaction.
Below is your example implemented with pg-promise, using ES7 syntax:
const pgp = require('pg-promise')({
// initialization options;
});
const db = pgp(/* your connection object or string */);
db.tx(async t => {
const user = await t.one('INSERT INTO user(status, create_date) VALUES($1, $2) RETURNING id', [status, timestamp]);
return t.none('INSERT INTO user_information(user_id, email) VALUES($1, $2)', [user.id, email]);
})
.then(() => {
// SUCCESS;
})
.catch(error => {
// ERROR;
});
I do not believe this can be accomplished as a natural sql statement. You have to wrap it up as a procedure or some other mechanism.

node-mysql connection.query() returns undefined

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.

Categories