I have a JSON like this:
{"name":[{"tag":"Peter"}]}
And I'm dynamically building a prepared statement with multiple wildcards like this:
var sqlVar;
sqlVar += existParams.map(field => {
if (field === 'name') {
function getValues(item, index) {
var getVal = [item.tag];
return `${field} LIKE ?`;
}
return '('+name.map(getValues).join(' OR ')+')';
} else {
return `(${field} = ?)`
}
}).join(" AND ");
var sql = "SELECT * FROM names "+sqlVar+"";
connection.query(sql,
...
function getValues(item, index) {
var getVal = [item.tag];
return '%' + getVal + '%';
}
return name.map(getValues);
//Further attempts
//var getResult = name.map(getValues);
//return getResult.split(",");
//return name.map(getValues).join(', ');
, function(err, rows) {
...
});
If I have one value it works just fine. In console.log (SQL) I can see:
SELECT * FROM names WHERE (name LIKE ?)
BUT... if I have multiple values like:
{"name":[{"tag":"Peter"},{"tag":"Jack"}]}
I'm getting an SQL Error:
sql: 'SELECT * FROM names WHERE (name LIKE \'%Peter%\', \'%Jack%\' OR name LIKE ?) }
... So the second value is not going to the second position.
... but the result should be:
sql: 'SELECT * FROM names WHERE (name LIKE \'%Jack%\' OR name LIKE \'%Peter%\') }
... so in the console.log(sql):
SELECT * FROM names WHERE (name LIKE ? OR name LIKE ?)
What am I missing and how can I get the second value to the second LIKE and so on?!
Here is a similar example but with only one value: nodejs throws error with mysql like query via prepared statements
The only reason here for the resulting statement to be 'SELECT * FROM names WHERE (name LIKE \'%Peter%\', \'%Jack%\' OR name LIKE ?)
is that you have passed a nested array with value [['%Peter%', '%Jack%']] instead of a flat one.
Using the given object say,
const source = {"name":[{"tag":"Peter"}, {"tag":"Jack"}]}
Then the query values for the prepared statement should be
const queryValues = source.name.map(({tag}) => `%${tag}%`);
// [ '%Peter%', '%Jack%' ]
connect.query(sql, queryValues, (err, rows) => {
});
Related
I'm trying to create a filter for a findAll function that filters by name. The other filters in this function work fine but I can't get the name filter to work.
The function below accepts filter parameters (if any) and adds on to the WHERE query based on any passed in filters. Right now, when I pass in a name, it returns nothing unless the query matches a name in the database but I'm trying to return results that contain whatever the value of name is (i.e. a name query for 'net' would get you 'Neural Networks')
Here is what I have so far:
static async findAll(searchFilters = {}) {
let query = `SELECT handle, name, description, num_employees AS "numEmployees", logo_url AS "logoUrl"
FROM companies`;
let whereStatement = []
let values = []
const {name, minEmployees, maxEmployees} = searchFilters
if (minEmployees > maxEmployees) throw new BadRequestError('minEmployees cannot be greater than maxEmployees!')
if (!!minEmployees) {
values.push(minEmployees)
whereStatement.push(`num_employees >= $${values.length}`)
}
if (!!maxEmployees) {
values.push(maxEmployees)
whereStatement.push(`num_employees <= $${values.length}`)
}
if (!!name) {
values.push(name)
whereStatement.push(`name ILIKE $${values.length}`)
}
if (whereStatement.length > 0) {
query += ` WHERE ${whereStatement.join(" AND ")}`
}
query += ' ORDER BY name'
const companiesRes = await db.query(query, values)
return companiesRes.rows;
}
I tried typing it like this:
name ILIKE '%$${values.length}%'
but I got this message:
"error": {
"message": "bind message supplies 1 parameters, but prepared statement \"\" requires 0",
"status": 500
}
Is there a specific way to sanitize ILIKE queries in Node-pg or is my syntax just off?
I think your code in place where you append the name filter should look like:
...
if (!!name) {
values.push(`%${name}%`)
whereStatement.push(`name ILIKE $${values.length}`)
}
...
see 503#issuecomment-32055380
I have situation where I need to write a sql select query which is technically need to be repeated to all the items in a list.
For example, say I have list like this,
list =[ { item_1: value_11,
item_2: value_12,
item_3: value_13,
item_4: value_14'
},
{ item_1: value_21,
item_2: value_22,
item_3: value_23,
item_4: value_24,
},
{ item_1: value_31,
item_2: value_32,
item_3: value_33,
item_4: value_34,
},
......
];
Now I need to write a SELECT query to get all the related records for each of the item, something like,
//for each item
SELECT * FROM tbl WHERE tbl.fld1 = list[0].item_1 AND tbl.fld2 = list[0].item_2 AND tbl.fld3 = list[0].item_3 AND tbl.fld4 = list[0].item_4;
Is it possible to write a single query for the same within SQL statement (kind of loop) or else does it need to be repeated from the coding side so it will call the db for each items separately.
Please help,
Thank You in advance
As #draz already commented you need to loop over the list to dynamically create the sql statement. You can loop over it in your code and generate a single sql statement that can be send to the database once.
A simple but probably not the nicest idea would be something like:
sql_select = "SELECT * FROM tbl WHERE";
first_item = true;
for (element in list) {
sql_select = (first_item) ? sql_select : sql_select + " OR";
fist_item = false;
where_clause = ` (tbl.fld1 = ${element.item_1} AND tbl.fld2 = ${element.item_2} AND tbl.fld3 = ${element.item_3} AND tbl.fld4 = ${element.item_4})`;
sql_select.concat(where_clause);
}
I am working on a webshop-project. I am trying to get sorted results based on parameter values from a sqlite database. I am trying to sort products based on "select" values.
In my app.js
app.get('/sortMaleProducts', function(request, response){
var sortValues = request.query.sortValue;
if(sortValues == 'priceASC')
{
sortValues = ["man", "price", "ASC"];
}
else if(sortValues == 'priceDESC')
{
sortValues = ["man", "price", "DESC"];
}
db.sortMaleProducts(sortValues, function(error, clothes){
if(error){
console.log("Error: "+ error);
}
else{
console.log(clothes)
const model = {
clothes
}
response.render("man.hbs", model)
}
})
})
In my db.js
exports.sortMaleProducts = function(sortValues, callback){
const query = 'SELECT * FROM products WHERE gender = ? Order by ?, ?'
db.all(query, sortValues, function(error, clothes){
console.log(clothes);
callback(error, clothes);
})
If I hardcode the query like:
const query = 'SELECT * FROM products WHERE gender = 'man' Order by price ASC'
Then it works....But I want to use user inputs so I can reuse code..
If you want to sort by a column, that column name has to appear directly in the query. What you're doing sorts the results by the strings 'price' and 'ASC', which are the same for every row so any order of results is sorted.
You can't use column names as parameters anywhere else in a query either, like in the columns to return or in a WHERE. They have to be present when the statement is prepared by compiling it into sqlite's internal bytecode, which happens before any parameter binding or the execution of the query.
var which = {};
which['creditcards'] = "tx.executeSql('SELECT * FROM " + table + " ', [], querySucess, errorCB)";
db.transaction(function(tx){
which[table];
});
I want to be able to dynamically insert the select statement based on the variable clicked. Is this possible? Am I going about it the right way?
Yes it's possible but no, you don't appear to be going about it the right way - I'd expect something more like the following:
function dbQueryWrapper(table) { // table is a string supplied from onclick etc
db.transaction (
function(tx) {
tx.executeSql(
'SELECT * FROM ?;', [ table ], querySucess, errorCB
);
}
);
}
The second param with the [] is an array of stuff you want to pass into your query - each item fills on ? in the query
function insertToProject(cast, pName)
{
db.execute('INSERT INTO project (cd, pn) VALUES (?,?)', cast, pName);
var x = last_insert_rowid();
return x;
}
I have been trying this using javascript in titanium appcelerator. Can anybody tell me what I am doing wrong?
For this you can use the lastInsertRowId property of database object.
You can use like:
var x = db.lastInsertRowId;
lastInsertRowId
lastInsertRowId : Number
The identifier of the last populated row
Please check this link for more details : Titanium.Database.DB
You may also do:
db.transaction(function(tx) {
tx.executeSql("INSERT INTO project (cd, pn) VALUES (?,?)", cast,
function(tx, res) {
var id = res.insertId;
});
});
Thus, getting the result of the successful insert and then its property insertId