Pass variables to DATABASE preventing mysql injection node and mysql - mysql

So, I started to develop in nodejs and mysql. I read in some forums that the correct way to do the insertion in mysql would be using variables to prevent mysql injection, however I tried in several ways to insert them and I couldn't. I was only able to do them manually as follows:
db.query('UPDATE spreadsheetUsers SET weight="1" WHERE weekDay="1" AND idStudent="1" ', (error,results) =>
How could I do to insert them using variables?
The way I was trying was like this:
db.query('UPDATE spreadsheetUsers SET weight=? WHERE weekDay=? AND idStudent=? '
,{weight:value[0], weekDay:daySelected, idStudent:idStudent }, (error,results) =>
I guess im missing something, could someone help?

https://github.com/mysqljs/mysql#escaping-query-values
{weight:value[0], weekDay:daySelected, idStudent:idStudent }, (error,results) =>
the parameterized query should be array not object
db.query('UPDATE spreadsheetUsers SET weight=? WHERE weekDay=? AND idStudent=?'
,[value[0], daySelected, idStudent], (error,results) =>
You can use this style also
db.query({
sql: 'UPDATE spreadsheetUsers SET weight=? WHERE weekDay=? AND idStudent=?',
values: [value[0], daySelected, idStudent']
}, 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)
});

Related

MySQL binding multiple parameters to a single query

I have a MySql database, and I'm connecting to it from a .Net app using Dapper. I have the following code:
await connection.ExecuteAsync(
"DELETE FROM my_data_table WHERE somedata IN (#data)",
new { data = datalist.Select(a => a.dataitem1).ToArray() },
trans);
When I do this with more than a single value, I get the following error:
MySqlConnector.MySqlException: 'Operand should contain 1 column(s)'
Is what I'm trying to do possible in MySql / Dapper, or do I have to issue a query per line I wish to delete?
Your original code was almost fine. You just need to remove the parentheses around the parameter. Dapper will insert those for you:
await connection.ExecuteAsync(
"DELETE FROM my_data_table WHERE somedata IN #data",
new { data = datalist.Select(a => a.dataitem1).ToArray() },
trans);

converting SQL into KNEX multiple conditions

I'm trying to convert my SQL into KNEX. what I have so far is:
SQL:
SELECT name from students where attendance = "90" AND timestamp between "2020-05-14" AND "2020-05-18";
my attempt to convert to KNEX:
const from = req.query.from;
const to = req.query.to
router.get('/students/attendance?from=&to='
req.db.from('students').select("*").where('attendance', '=', req.params.attendance).andWhere('timestamp', 'between', [from, to])
MYSQL code works and returns what I want but I'm assuming my syntax is wrong with the Knex. Push in the right direction please
Where between is documented here https://knexjs.org/#Builder-whereBetween
await req.db
.from('students')
.select("*")
.where('attendance', req.params.attendance)
.whereBetween('timestamp', [from, to])
Also you can use .toSQL() to inspect the built query query.

Pass array in Mysql query with nodejs

I have a simple query that I want to pass an array inside which has 5 items. I am using the mysql module so I know it can be done but am not doing the synatx right and therefore getting a syntax error.
Below is the query:
`UPDATE table1 SET table1.col=0 WHERE (table1.col2) IN = (?) AND table1.id=(SELECT ...);`,[arr]
//arr = [1,2,3,4,5];
I have tried:
`UPDATE table1 SET table1.col=0 WHERE (table1.col2) IN = (?,?,?,?,?) AND table1.id=(SELECT ...);`,[arr]`
but I still get a syntax error.
Adding on to Bill Karwin's answer, you can also pass an array to the MySQL query against the '?' placeholder in the same way
WHERE table1.col2 IN (?)
//arr = [1,2,3,4,5];
Passing arr along with the query will convert it to the required SQL string. The mysql module uses the 'SqlString.arrayToList' function from 'sqlstring' module internally for the transformation:
https://github.com/mysqljs/sqlstring/blob/8f193cae10a2208010102fd50f0b61e869e14dcb/lib/SqlString.js#L60
In my case, array inside of array is needed to get this working. Just array variable as parameter passed only first number to sql.
Here is an example: (Notice ids inside of array as the second parameter)
var sql = "SELECT * FROM table WHERE ID IN (?)";
var ids = [1,2,3];
pool.query(sql, [ids], function (err, result, fields) {
if(err) {
console.log(err);
}
else {
console.log(result);
}
}
The syntax of the IN() predicate does not use =.
WHERE (table1.col2) IN = (?,?,?,?,?)
should be
WHERE table1.col2 IN (?,?,?,?,?)
Tip: you can (and should) check syntax yourself in the documentation, so you can get answers more easily than posting to Stack Overflow.
https://dev.mysql.com/doc/refman/5.7/en/comparison-operators.html#function_in

NodeJS - Sequelize updating issue

I have a problem with updating method.
I am doing this:
// Char is outside the object where update method is...
Char = db.define('characters', {}, {
tableName: 'characters',
updatedAt: false,
createdAt: false
});
//... part of the whole object
update: function ( columns, callback ) {
Char.update( columns, { where: { id: this.get('char_id') } } )
.complete( function ( err, res ) {
f.log(res, 'd');
});
},
When I define updatedAt to be false, the updates stop working at all and I don't know how to prevent that, except to add a column in my database. It throws me "Query was empty".
So I tried to define updatedAt as 'created_at' - an existing column in my table and then the updates have worked, but not at all. The query updating only 'created_at' with the timestamp, but not my preferred columns.
Example that I receive in the console:
Executing (default): UPDATE characters SET created_at='2015-02-03 21:03:00' WHERE id='1'
It should be:
Executing (default): UPDATE characters SET health = ..., created_at='2015-02-03 21:03:00' WHERE id='1'
I debug whether the columns parameter is valid parameter. Yes, it is - I send an object and receive an object.
Can someone help me. I tried old ways, new ways, read posts, but nothing.
EDIT:
I found where I'm wrong. I should define all fields which I want to update/insert.
Because of my english I didn't understand right the define function in documentation. I thought that when you define the fields you'll recreate your table structure, but now I realize, that that would happen if run sync() method.
I found where I'm wrong. I should define all fields which I want to update/insert. Because of my english I didn't understand right the define function in documentation. I thought that when you define the fields you'll recreate your table structure, but now I realize, that that would happen if run sync() method.

How to get Ruby MySQL returning PHP like DB SELECT result

So I use the PDO for a DB connection like this:
$this->dsn[$key] = array('mysql:host=' . $creds['SRVR'] . ';dbname=' . $db, $creds['USER'], $creds['PWD']);
$this->db[$key] = new PDO($this->dsn[$key]);
Using PDO I can then execute a MySQL SELECT using something like this:
$sql = "SELECT * FROM table WHERE id = ?";
$st = $db->prepare($sql);
$st->execute($id);
$result = $st->fetchAll();
The $result variable will then return an array of arrays where each row is given a incremental key - the first row having the array key 0. And then that data will have an array the DB data like this:
$result (array(2)
[0]=>[0=>1, "id"=>1, 1=>"stuff", "field1"=>"stuff", 2=>"more stuff", "field2"=>"more stuff" ...],
[1]=>[0=>2, "id"=>2, 1=>"yet more stuff", "field1"=>"yet more stuff", 2=>"even more stuff", "field2"=>"even more stuff"]);
In this example the DB table's field names would be id, field1 and field2. And the result allows you to spin through the array of data rows and then access the data using either a index (0, 1, 2) or the field name ("id", "field1", "field2"). Most of the time I prefer to access the data via the field names but access via both means is useful.
So I'm learning the ruby-mysql gem right now and I can retrieve the data from the DB. However, I cannot get the field names. I could probably extract it from the SQL statement given but that requires a fair bit of coding for error trapping and only works so long as I'm not using SELECT * FROM ... as my SELECT statement.
So I'm using a table full of State names and their abbreviations for my testing. When I use "SELECT State, Abbr FROM states" with the following code
st = #db.prepare(sql)
if empty(where)
st.execute()
else
st.execute(where)
end
rows = []
while row = st.fetch do
rows << row
end
st.close
return rows
I get a result like this:
[["Alabama", "AL"], ["Alaska", "AK"], ...]
And I'm wanting a result like this:
[[0=>"Alabama", "State"=>"Alabama", 1=>"AL", "Abbr"=>"AL"], ...]
I'm guessing I don't have the way inspect would display it quite right but I'm hoping you get the idea by now.
Anyway to do this? I've seen some reference to doing this type of thing but it appears to require the DBI module. I guess that isn't the end of the world but is that the only way? Or can I do it with ruby-mysql alone?
I've been digging into all the methods I can find without success. Hopefully you guys can help.
Thanks
Gabe
You can do this yourself without too much effort:
expanded_rows = rows.map do |r|
{ 0 => r[0], 'State' => r[0], 1 => r[1], 'Abbr' => r[1] }
end
Or a more general approach that you could wrap up in a method:
columns = ['State', 'Abbr']
expanded_rows = rows.map do |r|
0.upto(names.length - 1).each_with_object({}) do |i, h|
h[names[i]] = h[i] = r[i]
end
end
So you could collect up the rows as you are now and then pump that array of arrays through something like what's above and you should get the sort of data structure you're looking for out the other side.
There are other methods on the row you get from st.fetch as well:
http://rubydoc.info/gems/mysql/2.8.1/Mysql/Result
But you'll have to experiment a little to see what exactly they return as the documentation is, um, a little thin.
You should be able to get the column names out of row or st:
http://rubydoc.info/gems/mysql/2.8.1/Mysql/Stmt
but again, you'll have to experiment to figure out the API. Sorry, I don't have anything set up to play around with the MySQL API that you're using so I can't be more specific.
I realize that php programmers are all cowboys who think using a db layer is cheating, but you should really consider activerecord.