Using the LIKE operator in MYSQL voids the "id > ? operation" - mysql

I am using the like operator to select where like %x% and using the id > ? at the same time but it doesn't work for whatever reason where I keep pulling in the same row of information.
My code is concise and works well I think but the like operator is making it so I keep pulling in the same data (I used = and it worked). Any help please, thank you.
var query = 'SELECT * FROM products WHERE 1 = 1';
var arr = [];
if(typeof(req.body.category) == 'string' && req.body.category.trim() !== '') {
// query += ' AND category LIKE ? OR title LIKE ?'; //doesnt work keep pulling in same data
// arr.push('%' + req.body.category + '%', '%' + req.body.category + '%'); //doesnt work keep pulling in same data
// query += ' AND category = ? OR title = ?'; //works
// arr.push(req.body.category, req.body.category); //works
}
if(typeof(req.body.reset_index) == 'boolean' && req.body.reset_index == true) {
req.session.last_id_main_products = 0;
}
query += ' AND id > ?';
arr.push(req.session.last_id_main_products);
if(
typeof(req.body.longitude) == 'number' &&
typeof(req.body.latitude) == 'number' &&
typeof(req.body.if_location) == 'boolean' && req.body.if_location == true
) {
var left_long = req.body.longitude - 0.3;
var right_long = req.body.longitude + 0.3;
var upper_lat = req.body.latitude + 0.3;
var lower_lat = req.body.latitude - 0.3;
query += ' AND (room_geo_longitude > ? AND room_geo_longitude < ?) AND (room_geo_latitude > ? AND room_geo_latitude < ?)';
arr.push(left_long, right_long, lower_lat, upper_lat);
}
query += ' AND hidden = false LIMIT 1';
pool.query(query, arr, (err, result) => {
if(err) {
res.json(err);
return;
}
if(result.length > 0) {
req.session.last_id_main_products = result[result.length - 1].id;
}
res.json({
room_products: result,
query: query,
arr: arr
});
});
UPDATE: When using query, use parentheses around specific types of operations or else will return bad data.

Related

Doesn't execute dynamic mysql query in nodejs

I am trying to execute a dynamic query needed for an api written using nodejs as server language and mysql as db. The query that i have written is a dynamic query and the query used UNION to join two queries. For some reason, it doesn't take the seconds conditions.where in the sql query and give the below error message.
"You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '?) AND r.ReviewRating IN (?) AND r.Title IS NOT NULL AND r.DateCreated BETWEEN (' at line 1"
Below is the function in my modal class.:
getReviewsAndPhotoReportBySellerId: (sellerId, reviewRating, title, photoAvailable, dateFrom, dateTo, callback) => {
//Dynamic Query Generation based on user input
function buildConditions() {
var conditions = [];
var values = [];
if (typeof sellerId !== 'undefined') {
conditions.push("r.SellerId IN (?)");
values.push(sellerId);
}
if (typeof reviewRating !== 'undefined') {
conditions.push("r.ReviewRating IN (?)");
values.push(reviewRating);
}
if(title == "has comment"){
conditions.push("r.Title IS NOT NULL");
}else if(title == "no comment"){
conditions.push("r.Title IS NULL");
}
if(photoAvailable == 1){
conditions.push("rp.ReviewImageUrl1 IS NOT NULL || rp.ReviewImageUrl2 IS NOT NULL || rp.ReviewImageUrl3 IS NOT NULL");
}else if(photoAvailable == 'undefined'){
conditions.push("rp.ReviewImageUrl1 IS NULL && rp.ReviewImageUrl2 IS NULL && rp.ReviewImageUrl3 IS NULL");
}
if(typeof dateFrom !== 'undefined' && typeof dateTo !== 'undefined' ){
conditions.push("r.DateCreated BETWEEN (?) AND (?) ");
values.push(dateFrom);
values.push(dateTo);
}
return {
where: conditions.length ?
conditions.join(' AND ') : '1',
values: values
};
}
var conditions = buildConditions();
var sql =
'(select *, r.ReviewId AS ActualReviewId, r.DateCreated AS ActualDateCreated from review r LEFT join reviewphoto rp ON r.ReviewId = rp.ReviewId WHERE '
+ conditions.where
+ ') UNION '
+ '(select *, r.ReviewId AS ActualReviewId, r.DateCreated AS ActualDateCreated from review r RIGHT join reviewphoto rp ON r.ReviewId = rp.ReviewId WHERE '
+ conditions.where
+ ') ORDER BY ActualDateCreated DESC ';
console.log(sql);
pool.query(sql, conditions.values, (error, results, fields) => {
if (error) {
callback(error);
}
return callback(null, results);
}
);
},

How do I insert a mysql row from Object (in nodeJS)?

Right now I use this cumbersome approach when I want to add a row whose data is in a JS Object
Adding a row to a table:
const mysql = require('mysql')
var db = mysql.createConnection(DBInfo)
var databaseObj = {val1: '1', name: 'John', age: 40} // row to insert
var query = 'INSERT INTO my_table ('
var databaseKeys = Object.keys(databaseObj)
for (let i = 0; i < databaseKeys.length; i++) {
query += databaseKeys[i] + (i !== databaseKeys.length - 1 ? ', ' : ')')
}
query += ' ' + 'VALUES('
for (let i = 0; i < databaseKeys.length; i++) {
query += '\'' + databaseObj[databaseKeys[i]] + '\'' + (i !== databaseKeys.length - 1 ? ', ' : ')')
}
db.query(query, function (err, results, fields) {...
Is there any simpler or neater way to add a row into a table, where such row data is in a JS Object? The examples I see around use an array of arrays, but in my case the info is in a Object
I should use the INSERT into table SET because they are equivalent
var db = mysql.createConnection(DBInfo)
var databaseObj = {val1: '1', name: 'John', age: 40}
var query = 'INSERT INTO my_table SET ' + db.escape(databaseObj)
db.query(query, function (err, results, fields) {...

NodeJS vs Laravel with Mysql Database which one better in term of performance

I am developing a REST Back-End with MYSQL database,now i need to choose between which server side language its better in term of less server resources (CPU and Ram) consuming .
Let say for example, i have a POST end point for (register a new user account) and another GET end point for (getting the user info in JSON format). and i am expecting a high traffic on my website, which programming language will consume more server resources ?
I have googled to compare between both NodejS and Laravel, i found some websites showing a benchmark test with a favor of laravel and other website showing that NodeJS is better.
With basic get/set DB operations there isn't going to be significant time in whichever language you choose.
Choose a language based on non-performance criteria and solve specific performance problems as they arise.
As you've tag load-balancing I assume you application is already horizontally scaleable.
I built myself sql script writer like this, it's pretty fast for my project since my previous PHP Backend is too slow (in my case)
const mysqlLib = require('mysql');
const ENV = require('../configs/env').ENV;
const database = ENV.database;
const mysql = mysqlLib.createPool(database);
function executeQuery(query) {
return new Promise((resolve, reject) => {
mysql.query(query, (err, result, fields) => {
if (err) {
console.log(query);
return reject(err);
}
resolve(result);
});
});
}
function executeQueryGetFirst(query) {
return new Promise((resolve, reject) => {
mysql.query(query, (err, result, fields) => {
if (err) {
console.log(query);
return reject(err);
}
result = JSON.parse(JSON.stringify(result));
if (result.length == 0) {
resolve(null);
} else {
resolve(result[0]);
}
});
});
}
var Database = {
getById(table, id) {
var query = '';
query += 'SELECT * FROM ' + table + ' ';
query += 'WHERE Id = ' + id;
query += ' LIMIT 1';
return executeQueryGetFirst(query);
},
getAllById(table, id) {
var query = '';
query += 'SELECT * FROM ' + table + ' ';
query += 'WHERE Id = ' + id;
return executeQuery(query);
},
getByAttributes(table, attributes) {
var query = 'SELECT * FROM ' + table;
var whereQuery = '';
for (prop in attributes) {
if (whereQuery != '') {
whereQuery += ' AND ';
}
if (attributes[prop] == null) {
whereQuery += prop + ' IS NULL';
} else {
whereQuery += prop + ' = "' + attributes[prop] + '"';
}
}
query += ' WHERE ' + whereQuery;
query += ' LIMIT 1';
return executeQueryGetFirst(query);
},
getAllByAttributes(table, attributes) {
var query = 'SELECT * FROM ' + table;
var whereQuery = '';
for (prop in attributes) {
if (whereQuery != '') {
whereQuery += ' AND ';
}
if (attributes[prop] == null) {
whereQuery += prop + ' IS NULL';
} else {
whereQuery += prop + ' = "' + attributes[prop] + '"';
}
}
query += ' WHERE ' + whereQuery;
return executeQuery(query);
},
getAll(table) {
var query = 'SELECT * FROM ' + table;
return executeQuery(query);
},
add(table, attributes) {
var insertName = '(Id';
var insertData = '(NULL';
for (prop in attributes) {
var value = attributes[prop];
if (value != null) {
value = '"' + value + '"';
}
insertName += ', ' + prop;
insertData += ', ' + value;
}
insertName += ')';
insertData += ')';
var query = 'INSERT INTO ' + table + ' ' + insertName + ' VALUES ' + insertData;
return executeQuery(query);
},
updateByID(table, id, attributes) {
var query = 'UPDATE ' + table;
var setQuery = '';
for (prop in attributes) {
if (setQuery != '') {
setQuery += ', ';
}
setQuery += prop + ' = "' + attributes[prop] + '"';
}
query += ' SET ' + setQuery + ' WHERE Id = ' + id;
return executeQuery(query);
},
updateByAttributes(table, findAttributes, attributes) {
var query = 'UPDATE ' + table;
var setQuery = '';
var whereQuery = '';
for (prop in attributes) {
if (setQuery != '') {
setQuery += ', ';
}
setQuery += prop + ' = "' + attributes[prop] + '"';
}
for (prop in findAttributes) {
if (whereQuery != '') {
whereQuery += ', ';
}
whereQuery += prop + ' = "' + findAttributes[prop] + '"';
}
query += ' SET ' + setQuery + ' WHERE ' + whereQuery;
return executeQuery(query);
},
deleteById(table, id) {
var query = 'DELETE FROM ' + table + ' WHERE Id = ' + id;
return executeQuery(query);
},
deleteByAttributes(table, attributes) {
var query = 'DELETE FROM ' + table;
var whereQuery = '';
for (prop in attributes) {
if (whereQuery != '') {
whereQuery += ' AND ';
}
whereQuery += prop + ' = "' + attributes[prop] + '"';
}
query += ' WHERE ' + whereQuery;
return executeQuery(query);
}
}
Database.executeQuery = executeQuery;
Database.executeQueryGetFirst = executeQueryGetFirst;
exports.Database = Database;
Env config
var ENV = {
isDev: true,
database: {
connectionLimit: 10,
host: 'localhost',
user: 'root',
password: '',
database: 'your_database'
}
}
exports.ENV = ENV;
exports.ENV.port = ENV.isDev ? 15001 : 8887;

How to build dynamic query by binding parameters in node.js-sql?

I'm using nodejs-mysql module to do query in node.js recently, and in my working case I could only use the parameter-binding syntax like:
SELECT * FROM table WHERE name = ?
Now I want to build dynamic sql with these ? OR ?? parameters. Assume that I have 2 conditions(name and age) which either of them could be null (if user doesn't provide it),
So I want to build MySQL in 3 cases:
only name=Bob: SELECT * FROM table WHERE name = 'Bob'
only age=40: SELECT * FROM table WHERE age > 40
both: SELECT * FROM table WHERE name = 'Bob' AND age > 40
I know it's easy if you build the query on your own, but how can I achieve it when using placeholders which can only bind field or values ?
In document of nodejs-mysql, placeholder ? only stands for values and ?? stands for fields:
https://github.com/felixge/node-mysql/#escaping-query-values
https://github.com/felixge/node-mysql/#escaping-query-identifiers
My first thinking of solution is to insert query piece by using these placeholders, but it comes to failure because both ? and ?? will escape my query piece, and my query will be executed incorrectly.
My code so far is as below, which I'm defenitly sure it's not correct because query piece has been escaped:
// achieve paramters from url request
var condition = {};
if(params.name)condition["name"] = ["LIKE", "%" + params.name + "%"];
if(params.age)condition["age"] = parseInt(params.age, 10);
//build query
var sqlPiece = buildQuery(condition);
//try to replace ? with query
var sql = 'SELECT * FROM table WHERE ?';
connection.query(sql, sqlPiece, function(err, results) {
// do things
});
// my own query build function to proceed conditions
function buildQuery(condition) {
var conditionArray = [];
for(var field in condition){
var con = condition[field];
if(con !== undefined){
field = arguments[1] ? arguments[1] + "." + field : field;
var subCondition;
if(con instanceof Array) {
subCondition = field + " " + con[0] + " " + wrapString(con[1]);
}else{
subCondition = field + " = " + wrapString(con);
}
conditionArray.push(subCondition);
}
}
return conditionArray.length > 0 ? conditionArray.join(" AND ") : "1";
}
//wrap string value
function wrapString(value){
return typeof value === "string" ? "'" + value + "'" : value;
}
So is there any way I can fix this problem?
Update
Thanks to Jordan's Offer, it's working, but :
I know building query by string concat is very good, but in my case I can't use that, because I'm using some middleware or handle mysql and controller, so what I can do is to define interface, which is a sql string with placeholders. So, the interface string is predefined before, and I can't modify it during my controller function.
You're off to a really good start, but you may have been overthinking it a bit. The trick is to build a query with placeholders (?) as a string and simultaneously build an array of values.
So, if you have params = { name: 'foo', age: 40 }, you want to build the following objects:
where = 'name LIKE ? AND age = ?';
values = [ '%foo%', 40 ];
If you only have { name: 'foo' }, you'll build these instead:
where = 'name LIKE ?';
values = [ '%foo%' ];
Either way, you can use those objects directly in the query method, i.e.:
var sql = 'SELECT * FROM table WHERE ' + where;
connection.query(sql, values, function...);
How do we build those objects, then? In fact, the code is really similar to your buildQuery function, but less complex.
function buildConditions(params) {
var conditions = [];
var values = [];
var conditionsStr;
if (typeof params.name !== 'undefined') {
conditions.push("name LIKE ?");
values.push("%" + params.name + "%");
}
if (typeof params.age !== 'undefined') {
conditions.push("age = ?");
values.push(parseInt(params.age));
}
return {
where: conditions.length ?
conditions.join(' AND ') : '1',
values: values
};
}
var conditions = buildConditions(params);
var sql = 'SELECT * FROM table WHERE ' + conditions.where;
connection.query(sql, conditions.values, function(err, results) {
// do things
});
For Inserting into MYSQL like DB:
function generateInsertQuery(data, tableName) {
let part1 = `INSERT INTO ${tableName} (`;
let part2 = ")",
part3 = "VALUES (",
part4 = ")";
let tableKeys = "",
tableValues = "";
for (let key in data) {
tableKeys += `${key},`;
tableValues += `'${data[key]}',`
}
tableKeys = tableKeys.slice(0, -1);
tableValues = tableValues.slice(0, -1);
let query = `${part1}${tableKeys}${part2} ${part3}${tableValues}${part4}`;
return query;
}
generateInsertQuery({name: "Sam", tel: 09090909, email: "address#domain.com"}, "Person")
Output:
INSERT INTO Person (name,tel,email) VALUES ('Sam','9090909','address#domain.com');
Code Snippet for Update query:
function generateUpdateQuery(data, tableName, clauseKey, clauseValue) {
let part1 = `UPDATE ${tableName} SET`;
let part2 = `WHERE ${clauseKey} = ${clauseValue};`; //Add any number of filter clause statements here
let updateString = "";
for (let key in data) {
updateString += `${key} = '${data[key]}',`;
}
updateString = updateString.slice(0, -1);
let query = `${part1} ${updateString} ${part2}`;
return query;
}
generateUpdateQuery({
name: "Tanjiro",
tel: 77777777,
email: "tanjiro#demonslayer.com"
}, "Person", "ID", 111);
Output:
UPDATE Person SET name = 'Tanjiro',tel = '77777777',email = 'tanjiro#demonslayer.com' WHERE ID = 111;
I modify your code #Jordan-Running
describe("Test generateFilterQuery", () => {
it("Query filter with params", () => {
let params = []
params.push(Query.generateParams("title", "%_%", "Coding"))
params.push(Query.generateParams("published", "=", true))
console.log(Query.generateFilterQuery(params))
});
});
const qInclude = require('./QueryInclude');
exports.generateParams = (name, eq, value) => {
return {
name: name,
eq: eq, // %_%, %_, _%, =, >, <, !=,
value: value
}
}
exports.generateFilterQuery = (params) => {
let conditions, values = []
let conditionsStr;
if (params.length == 0) {
return false
}
[conditions, values] = qInclude.queryCondition(params)
let build = {
where: conditions.length ?
conditions.join(' AND ') : '1',
values: values
};
let query = 'SELECT * FROM table WHERE ' + build.where;
return [query, build.values]
}
exports.queryCondition = (params) => {
var conditions = [];
var values = [];
params.forEach(item => {
switch (item.eq) {
case '=': {
conditions.push(item.name + " = ?");
values.push(item.value);
break;
}
case '!=': {
conditions.push(item.name + " != ?");
values.push(item.value);
break;
}
case '<': {
conditions.push(item.name + " < ?");
values.push(item.value);
break;
}
case '>': {
conditions.push(item.name + " > ?");
values.push(item.value);
break;
}
case '%_%': {
conditions.push(item.name + " LIKE ?");
values.push("%" + item.value + "%");
break;
}
case '%_': {
conditions.push(item.name + " LIKE ?");
values.push("%" + item.value);
break;
}
case '_%': {
conditions.push(item.name + " LIKE ?");
values.push(item.value + "%");
break;
}
}
});
return [conditions, values]
}

if statement in mysql query codeigniter

I have to execute a query checking if a variable is empty or not. like:
if($symbol == ""){
$data_array = $this->db->select('*')
->select_max('date')
->get('company')
->row_array();
}else{
$data_array = $this->db->select('*')
->select_max('date')
->where('symbol',$symbol)
->get('company')
->row_array();
}
How can I make it in a single query?
I think you can do it like this:
if($symbol == ""){
$where = "symbol != 0"; ##$where = "symbol != ''"; whichever suits your case
}else{
$where = "symbol = '".$symbol."'";
}
$data_array = $this->db->select('*')
->select_max('date')
->where($where, false, false)
->get('company')
->row_array();