NodeJS mysql if null or empty - mysql

I have code, which should execute if the table is not in mysql or "NULL" or empty.
mysqlConnection.query('SELECT `something` FROM `here` WHERE `dog` = \'' +info+ '\'', function(err, row, fields) {
if(err) {
console.log('Error1');
return;
}
else if (!row.length) {
console.log('Error2');
return;
}
else if (row[0].something == 'NULL' || row[0].something == '') {
console.log('Error3');
return;
}
console.log('Works');
});
So the thing is, if "something" is not in mysql, console shows Error2, but if "something" is in mysql, but if its NULL, console shows Works, so whats the problem? Im checking if something is NULL, but it wont show Error3. If table is empty, it shows Error3. Thanks for help.

I would try something like this:
mysqlConnection.query('SELECT `something` FROM `here` WHERE `dog` = ?', [info] function(err, row, fields) {
if(err) {
return console.log('Error1');
} else if (!row.length) {
return console.log('Error2');
} else if (!row[0].something) {
return console.log('Error3');
}
console.log('Works');
});
It's using a "falsy" check for row[0].something which will return false if the value is undefined, null or an empty string. It also fixes the injection attack vector that t.niese mentioned.

I am aware that I am 5 years and 9 months late, but for those of you struggling with this,
here's a solution. The table's value when empty is not NULL. I was having a similar problem in which I wanted to reset AUTO_INCREMENT to 1 when the table is empty. To detect when it's empty, we have to see if it has any element with the index 0. If it has an element, it would return something like: RowDataPacket { // data }. If it doesn't, it would return undefined. See where I'm going with this? Just add a conditional to see if the result[0] is undefined or not. Want some code to better understand it? Sure! Here it is:
db.query("SELECT * FROM tablename", (err, result) => {
if (err) throw err;
else {
// If the first element does not exist
if (result[0] == undefined) {
db.query("yourquery", (err) => {
if (err) throw err;
});
} else {
res.send(result);
}
}
});

If you think in a scenario when you receive an Array<any> when you run a SQL like select name from employee there are three concerns you should have:
If your statement did return something
If the property you are looking for exist
If the content of the property is null and you are expecting a null
As these concerns will occur hundreds of time, I use the following approach (in TypeScript):
let ret: Array<any> = connection.query('select name from employee',...);
for (let r of ret) {
name = getValueColumn(r,'name','This will be thrown if content is null');
};
export function getValueColumn(obj: any, fieldName: string, messageIfNull: string = null): any {
fieldName = fieldName.toLocaleLowerCase();
if (!obj) {
throw new CustomError(errorCodes.connection.rowNull, 'Linha nula e sem campos');
} else if (!obj.hasOwnProperty(fieldName)) {
throw new CustomError(errorCodes.connection.fieldDoesNotExist, 'Campo não existe -> ' + fieldName);
} else {
if (!obj[fieldName]) {
if (messageIfNull) {
throw new CustomError(errorCodes.connection.fieldWithNullValue, messageIfNull + '\n' + fieldName +
' com valores nulos ou campo invalido\n' + obj);
};
return null;
};
return obj[fieldName];
};
};
If you were to check the results with just if (!ret) {...}, it would be always false as an empty array is not null. So you would have to check if(!ret[0]) {..}
So all three concerns are handled and you don't need to be worried every time you want to parse the query.

Related

i want to split a result in mysql can you help me?

Well, first that's my code here
client.on('message', async (message) => { //فايف ام داتابيس
if(message.channel.type == 'dm') return;
var prefix = prefixx.get(message.guild.id);
if(message.author.bot) return;
if(message.content.toLowerCase().startsWith(prefix + 'ip')) {
if(!message.member.hasPermission('ADMINISTRATOR')) return message.channel.send('ما عندك رتبة عشان تستخدم الأمر هذا');
let args = message.content.split(" ");
connection1.query(
`select ifnull((select last_login from vrp_users where id = ${args[1]}),'لا يوجد ايدي بهذا الرقم') As ResultFound`, function (error, result, fields) {
if (error) throw error;
console.log(`Got IP of user ${args[1]}`);
if(!result) return message.channel.send('There is an error');
if(error) return message.channel.send('There is an error');
let embed = new Discord.MessageEmbed() .setColor('RANDOM') .setTitle(`اي بي ${args[1]}`) .setThumbnail(message.guild.iconURL( { dynamic : true } )) .setAuthor(client.user.tag, client.user.avatarURL( {dynamic : true} )) .addField('IP', `\`${result[0].ResultFound}\``);
message.channel.send(embed)
}
);
}
});
the result comes like this :
77.223.232.147 23:50:55 29/06/2020
i want the result be only the ip can you guys help me?
Try this:
.addField('IP', `\`${result[0].ResultFound.split(' ')[0]}\``);
For example, if the result is what you provided in your question:
const result = '77.223.232.147 23:50:55 29/06/2020'
// split the message by every space
const array = result.split(' ');
console.log(array[0]); // IP adress
console.log(array[1]); // time (I presume)
console.log(array[2]); // date

How to execute a list of SQL commands sequentially?

I'm using MySQL for NodeJS and trying to do something like this:
dbQueries = ['multiple', 'sql', 'statements', 'that', 'need', 'to', 'be', 'executed', 'in', 'order'];
executedQueries = 0;
dbConn = mysql.connect();
maxQueries = dbQueries.length;
dbQueries.forEach(async (dbQuery) => {
console.log("Start");
return dbConn.query(dbQuery, function(err, results, fields) {
console.log("Finish");
if (err) {
errorList.push({ err, results, fields, dbQuery });
}
executedQueries++;
if (executedQueries >= maxQueries) {
if (errorList.length > 0) {
console.log("Error: ", databaseTable.name, " Errors reported: ", errorList);
}
if (typeof(callbackFunc) === 'function') { callbackFunc(errorList, executedQueries); }
}
});
});
But what ends up happening is that sometimes queries finish out of order. I know this because I setup the columns, then modify the table by adding in primary keys etc, and it sometimes errors with Table 'blah.blah' doesn't exist. The errors change each time. I could see this due to there being multiple Starts before seeing multiple Finishes. Not sure if I am using async correctly or not.
I do not want to turn on multipleStatements if possible.
The main reason you are seeing unexpected result is because nodejs executes these queries asynchronously. Correct way to run multiple queries:
dbQueries = ['multiple', 'sql', 'statements', 'that', 'need', 'to', 'be', 'executed', 'in', 'order'];
dbConn = mysql.connect();
function runQueries(dbQueriesArr) {
if(dbQueriesArr.length === 0)
return;
var dbQuery = dbQueriesArr[0];
dbConn.query(dbQuery, function(err, results, fields) {
if (err) {
errorList.push({ err, results, fields, dbQuery });
}
var dbQueriesArr_rest = dbQueriesArr.splice(1);
runQueries(dbQueriesArr_rest);
});
}
runQueries(dbQueries);

mongodb + nodejs to find and return specific fields in documents

I'm trying to extract specific document fields from a mongodb collection (v 3.0.8 at MongoLab). The returned documents must fall within a date range. My goal is to extract specific fields from these documents. My nodejs code,
var query = {}, operator1 = {}, operator2 = {}, operator3 = {} ;
operator1.$gte = +startDate;
operator2.$lte = +endDate;
operator3.$ne = 'move';
query['xid'] = 1; // Problem here?
query['date'] = Object.assign(operator1, operator2);
query['type'] = operator3;
console.log(query);
MongoClient.connect(connection, function(err, db) {
if(err){
res.send(err);
} else {
db.collection('jbone')
.find(query)
.toArray(function(err, result){
console.log(err);
res.json(result);
});
};
});
If I opt to return all fields in the date range, the query works fine. If I select only field xid I get no results. My query object looks sensible according to the docs. console.log(err) gives:
{ xid: 1,
date: { '$gte': 20160101, '$lte': 20160107 },
type: { '$ne': 'move' } }
null
null is the err.
Can anyone help me understand what I'm doing wrong?
Or point me to another similar SO questions with an answer?
Thanks
To select the specific field could be done as below
.find(
{date: { '$gte': 20160101, '$lte': 20160107 }, type: { '$ne': 'move' }},
{ xid: 1} )
Sample codes as following.
query['date'] = Object.assign(operator1, operator2);
query['type'] = operator3;
db.collection('jbone')
.find(query, {xid: 1})
.toArray(function(err, result){
console.log(err);
res.json(result);
});

TypeError: Cannot read property 'name' of undefined

When i type the username which is there in Table "fun" i am not facing any error but when i type wrong name that is the name which is not there in the table am facing error this is the error and code is attached below.
app.post('/Fu',function(req,res,next){
var username = req.body.uname;
var password = req.body.pwd;
con.query('SELECT name FROM fun WHERE name = "' + username +'" ',function(err, result,fields) {
var w = result[0].name;
if( username == w ){
console.log("login successful");
}
else{
console.log("login not successful");
}
}
});
res.send("success1");
});
can someone please help with the error.
This error is probably related to the fact that, when username is not present in the table, result will be set to and empty array []. That means that it has no elements at all, so result[0] is undefined.
Make sure to check for that before trying to get result[0].name.
Also, I would suggest you a few things:
1) Add error checking before anything else;
2) You do not need to check if the name is equal to the result. The query you wrote will only return entries that already match that requirement;
3) Send the responses inside the callback function, otherwise, the user will get the "success1" answer before the query has even finished executing.
Here follows the resulting code:
app.post('/Fu',function(req, res, next){
var username = req.body.uname;
var password = req.body.pwd;
con.query('SELECT name FROM fun WHERE name = "' + username +'"', function(err, result,fields) {
if (err) {
response.sendStatus(500);
return;
}
if (result.lenght > 0) {
res.send('Login was successful');
} else {
res.send('Login was not successful');
}
});
});
Your problem is here:
var w = result[0].name;
Because the result set at [0] doesn't exist (query came back with nothing). you are trying to get the name value from something that is undefined.
Do something like this:
var w
if (result[0]) {
w = result[0].name
} else {
//your logic to handle this scenario
}
That assumes that whatever db querying library you use will return an array, even if empty. If it returns undefined instead of an empty array, your if statement would need to look more like: if (result && result[0])

nodejs parse mysql row to object

I'm a little newbie in node.js + mysql + object oriented.
Following question here I would like the 'Content' object to use the values returned by a mysql query. What I'm doing now I find it is really redundant and possibly stupid as rows[0] itself is the object I want to use. Any better way for doing this? Or different approach if this is wrong also appreciated.
(I'm using binary uuid keys that must be hex-stringifyed again to send as resource response)
content.js:
function Content() {
this.id = '';
this.name = '';
this.domain = '';
}
Content.prototype.validate = function(path, queryParams) {
...
return true;
};
Content.prototype.whatever = function(apiVersion, params, callback) {
...
return callback(null, newParams);
};
mysql.js:
MySQLDb.SELECT_CONTENT_ID = "SELECT id, name, domain FROM content WHERE id = UNHEX(?)";
MySQLDb.prototype.findContentByID = function(id, callback) {
this.dbConnection.query(MySQLDb.SELECT_CONTENT_ID, [ id ],
function(err, rows, fields) {
var content = new Content();
if (rows.length > 0) {
var i = 0;
for (var key in rows[0]) {
if (rows[0].hasOwnProperty(key) && content.hasOwnProperty(key)) {
// BINARY(16) --> HEX string
if (fields[i].columnType === 254) {
content[key] = rows[0][key].toString('hex').toUpperCase();
} else {
content[key] = rows[0][key];
}
} else {
console.log('Column ' + key + ' out of sync on table "content"');
}
i += 1;
}
}
callback(err, content);
});
};
contentRes.js:
contentRes.GETWhatever = function(req, res) {
db.findContentByID(req.params.id, function onContent(err, content) {
if (err || !content.validate(req.path, req.query)) {
return res.send({});
}
content.whatever(req.query.apiVersion, req.query.d,
function onWhateverdone(err, params) {
if (err) {
return res.send({});
}
return res.send(params);
});
});
};
I think a lot of people would say you are doing it generally the right way even though it admittedly feels redundant.
It might feel a little cleaner if you refactored your code such that you could call the Content() constructor with an optional object, in this case rows[0] although if you were keeping it clean you wouldn't have access to the fields so you would take a different approach to the data type conversion - either by selecting the HEX representation in query or simply having your Content() know it needs to convert the id property.
Keeping it fairly simple (by which I mean ignoring making the constructor a bit more intelligent as well as any error detection or handling), you would have:
function Content(baseObj) {
this.id = (baseObj && baseObj.id) ? baseObj.id.toString('hex').toUpperCase() : '';
this.name = (baseObj && baseObj.name) ? baseObj.name : '';
this.domain = (baseObj && baseObj.domain) ? baseObj.domain : '';
}
Then you could do something like this:
MySQLDb.prototype.findContentByID = function(id, callback) {
this.dbConnection.query(MySQLDb.SELECT_CONTENT_ID, [ id ],
function(err, rows, fields) {
if (err) return callback(err,null);
return callback(err, new Content(rows[0]));
});
You 'could' also grab the rows[0] object directly, HEX the UUID more or less in situ and modify the __proto__ of the object, or under Harmony/ES6 use the setPrototypeOf() method.
MySQLDb.prototype.findContentByID = function(id, callback) {
this.dbConnection.query(MySQLDb.SELECT_CONTENT_ID, [ id ],
function(err, rows, fields) {
if (err) return callback(err,null);
var content = rows[0];
content.id = content.id.toString('hex').toUpperCase();
content.__proto__ = Content.prototype;
return callback(err, content);
});
Note, I said you 'could' do this. Reasonable people can differ on whether you 'should' do this. __proto__ is deprecated (although it works just fine in Node from what I have seen). If you take this general approach, I would probably suggest using setPrototypeOf(), and install a polyfill until you are otherwise running with ES6.
Just trying to give you a couple of other more terse ways to do this, given that I think the redundancy/verbosity of the first version is what you didn't like. Hope it helps.