Express add backslash in insert - node.js

I'm working with express and Mysql trying to create a new record in my database but i'm getting one error in my console. This one show the value inside of backslash and i dont know why.
This is my function:
const PostImpuestos = (data,callback) => {
var sql = "INSERT INTO tbImpuesto (nombre, valor) VALUES ?";
connection.query(sql, [data] ,function(error,results){
if (results){
return callback()
} else {
console.log(error);
}
})
}
and this is the error:
sqlMessage:
'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 \'nombre = \'Impuesto de Tijuana\', valor = \'15%\'\' at line 1',
sqlState: '42000',
index: 0,
sql:
'INSERT INTO tbImpuesto (nombre, valor) VALUES nombre = \'Impuesto de Tijuana\', valor = \'15%\'' }
I was thinking the error could be something about type of the value data, because this is a json. I change it for array and object but the problem persists.

Simple fix you've got your insert query wrong you need to add ? for each variable you insert inside of brackets.
INSERT INTO tbImpuesto (nombre, valor) VALUES (?, ?);
The backslashes are just sanitzation to prevent sql injection.

Related

How to call stored proc in postgres using sequelize passing json parameter

I am new to postgresql and sequelize ORM.
I am trying to call a stored procedure which inserts data to a table.
CREATE OR REPLACE FUNCTION public.sp_eoi(
obj json)
RETURNS void
LANGUAGE 'sql' AS $BODY$
INSERT INTO public."tbl_eoi" ("SE_CUST_ID", "SE_VENDOR_ID", "SE_VENUE_ID")
SELECT (rec->>'custId')::integer, (rec->>'vendorId')::integer, (rec->>'venueId')::integer FROM
json_array_elements(obj-> 'data')rec $BODY$;
Json input passed from node application
{ custId : 1, vendorId : 1, venueId : 1}
I am calling proc
sequelize.query(
'call sp_eoi(:param)',
{replacements: { param: [ { custId:1 , vendorId: 1,venueId : 1 } ] }})
.spread(function(outputValue , records) {
console.log(records);
}).error(function(err){
res.json(err);
});
But there is always the error as "Unhandled rejection Error: Invalid value {custId: ..}
I am totally new to this and have been trying to find the problem for the last two days.
Any help would be really appreciated.
Thanks
A bit late for the party... however:
td; dr;
Postgres uses functions (you can call them stored procedures), but it does not CALL them, it SELECT them
Here's the link to a similar problem: https://stackoverflow.com/a/38115374/1163927

Sqlite bind or column index out of range but i've got the right number of parameters

My code is this:
db.run(`begin transaction;
replace into players (user_id, role) values ($id, $role);
update signed_up_users set finalised = 1 where user_id = $id;
commit;`, { $id: id, $role: role}, err=>{
if (err) {throw err;}
});
And I get the following error:
Error: SQLITE_RANGE: bind or column index out of range
--> in Database#run('begin transaction;\n replace into players (user_id, role) values (?, ?);\n update signed_up_users set finalised = 1 where user_id = ?;\n commit;', [ '123', 'INNOCENT', '123' ], [Function])
at Object.exports.finalise_user (C:\whatever\file.js)
at user.resolve_to_id.then.id (C:\whatever\file.js:52:14)
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:188:7)
If I understand the documentation correctly, I have the right amount of parameters and placeholders in my statement. So what am I doing wrong? Thanks.
The documentation actually says:
Database#run(sql, [param, ...], [callback])
Runs the SQL query […]
Database#exec(sql, [callback])
Runs all SQL queries in the supplied string.

Dynamic queries with knex-postgis

I am building a simple API that also deal with geometries (store into postGIS).
I am using knex-postgis to access the ST_ spatial functions in postGIS with knex.
I have used this example to insert a point and it work when its hard coded.
But my lack of experience is leave me hanging, how can I make the query dynamic? I want to create a form with input for x and y value and send it to the ST_geomFromText function to save it to the geom type in the db.
Is this when you would use parameters? Could someone point me in the right direction?
// insert a point
const sql1 = db.insert({
id: 1,
geom: st.geomFromText('Point(0 0)', 4326)
}).into('points').toString();
console.log(sql1);
// insert into "points" ("geom", "id") values
(ST_geomFromText('Point(0 0)'), '1')
So far I have tried
router.post('/', (req, res, next) => {
queries.create(req.body).then(poi => {
res.json(poi[0]);
});
});
Insert query
create(poi) {
const sql = db.insert(poi).returning('*').into('poi');
return sql;
},
In Postman I am sending this in its body
{
"place": "test",
"comments": "new",
"numbers": 6,
"geom": "st.geomFromText('Point(-71.064544 44.28787)', 4326)"
}
But get an error "Unhandled rejection error: parse error - invalid geometry"
The hard coded object looks the same and is work fine.
I have a feeling that I am using the st.geomFromText wrong, but i dont I am not sure?
This is what i get if i console.log returned query
insert into "poi" ("comments", "geom", "numbers", "place") values ('new', 'st.geomFromText(''Point(-71.064544 44.28787)'', 4326)', 6, 'test')
(see how it does not change st.geom.. to st_geom..? Also the quotation marks around the ST function and the Point object is not right)
This string work when I run it in pgAdmin
insert into "poi" ("comments", "geom", "numbers", "place") values ('new', st_GeomFromText('Point(-71.064544 44.28787)', 4326), 6, 'test')
EDIT:
I console.log the hardcoded version too. It does no appear to add the extra '' on the geometry value
insert into "poi" ("geom") values (ST_geomFromText('Point(-71.064544 44.28787)', 4326))
Any advice?
You pass coordinates from postman as string value in JSON object
"geom": "st.geomFromText('Point(-71.064544 44.28787)', 4326)"
And expect your code to transform it into a function call
st.geomFromText('Point(-71.064544 44.28787)', 4326)
What knex does in this case. It takes your string and convert it as it is string field (here you get a single quote ' replacement with double '' for Postgres to escape it).
What you can do. Pass your geometry to your API like this
"geom": "Point(-71.064544 44.28787)"
And in your route handler
create(poi) {
const sql = db.insert({
place: poi.place,
comments: poi.comments,
numbers: poi.numbers,
geom: st.geomFromText(poi.geom, 4326)
}).returning('*').into('poi');
return sql;
},

Node.js and sqlite, SQLITE_RANGE: bind or column index out of range

See my answer below for a MWE!
I know it sound stupid and the answer is probably right in front of me, but I can't figure out why I get this SQLITE_RANGE error, since my object looks like it has every properties needed.
console.log "values " , values
# Recording in db
console.assert values.login?
console.assert values.password_sha?
console.assert values.email?
console.assert values.token?
values.password = null
#db.run "INSERT INTO user VALUES (NULL, $login, $password_sha, $email, $token)", values, (err) ->
console.error err if err?
Here is the output of my server
values { login: 'ostream',
email: 'ijw',
password: 'justine',
token: 'acppn99ngiafw29',
password_sha: 'b1820c2ec34175954bdaa42038b48886b4c83f8d53f88b5315c415898855e4f8' }
{ [Error: SQLITE_RANGE: bind or column index out of range] errno: 25, code: 'SQLITE_RANGE' }
Thanks in advance!
Apparently what you need to do is make sure the keys in your user object are prefixed with $. Otherwise sqlite3 won't recognise them as values for placeholders. Try:
sqlite3 = require 'sqlite3'
db = new sqlite3.Database('testfile.db');
user =
$name: 'hello'
$password: 'jambon'
db.run 'insert into "user" (name, password) VALUES ($name, $password)', user, (err) ->
console.log 'request executed : ', err
It's not very well documented, but looking at the test cases you can see that there are other options, like prefixing them with # or :. In any case, your object has to match the placeholders including the prefix.
You should always specify column list when you INSERT:
INSERT INTO "user"(login, password_sha, email, token)
VALUES ('ostream',
'b1820c2ec34175954bdaa42038b48886b4c83f8d53f88b5315c415898855e4f8',
'ijw', 'acppn99ngiafw29');
SELECT *
FROM "user"
SqlFiddleDemo
Keep in mind that user is keyword and should be quoted with " or you can rename table to users.
Make sure the number of parameters matches.
For all SQL commands make sure the name of parameters matches.
Notice that $myValues != $myValue in my example:
let sqlRequest = "INSERT into myTable (myValue) VALUES ($myValue)";
let sqlParams = { $myValues: "Wrong parameter name" };
this.common.run(sqlRequest, sqlParams);

node-postgres prepared statement - sql injection

I am new to node-postgres and am unable to resolve this error when I try to ensure no sql injection is possible with my prepared statement.
Here is a snippet of the code
// the prepared statement
var preparedstatement = client.query({
text: "select ST_AsText(ST_Transform(geodata,4326)) from table_name where ST_Contains(ST_GeomFromText($1,4326),table_name.geodata)",
values: ["POINT(Lat Long)"],
name: 'where'
});
// the query
var queryresult = client.query({name: 'where', values: [msg]},["'; DROP TABLE user;"], function(err) {
if (err) {
socket.emit('query error', String(err));
}
});
Whenever I enter the geodata (as a message from the client using socket.io), the socket.emit returns an error saying
Invalid geometry
However the code works fine when I remove ["'; DROP TABLE user;"], from the code i.e.
// the query
var queryresult = client.query({name: 'where', values: [msg]}, function(err) {
if (err) {
socket.emit('query error', String(err));
}
});
(above) works perfectly. Any help in helping me understand what I am doing wrong here would be great.
var preparedstatement = client.query({
text: "select ST_AsText(ST_Transform(geodata,4326)) from table_name where ST_Contains(ST_GeomFromText($1,4326),table_name.geodata)",
values: ["POINT(Lat Long)"],
name: 'where'
});
results to SQL smth like
prepare "where" as
select ST_AsText(ST_Transform(geodata,4326))
from table_name
where ST_Contains(ST_GeomFromText($1,4326),table_name.geodata);
execute "where" (POINT(Lat Long));
which probably could work if lat nad long are table_name attributes
next:
var queryresult = client.query({name: 'where', values: [msg]}, function(err) {
if (err) {
socket.emit('query error', String(err));
}
});
does:
execute "where" (msg_value);
which probably works if they are of compatible data type
and finally:
var queryresult = client.query({name: 'where', values: [msg]},["'; DROP TABLE user;"], function(err) {
if (err) {
socket.emit('query error', String(err));
}
});
runs SQL:
execute "where" ('''; DROP TABLE user;');
which gives an error as this text is not a valid geometry...
noticable here that lient.query(text QUERY,array VALUES) here is used as lient.query(object QUERY,array VALUES) and VALUES overcame such in QUERY object, this your [msg] was "ignored"...
NB
checking if prepared statements are prune to such sql injection is pointless as this feature was implemented with idea to be safe for such injections. For example even if you would use data type text (to avoid type mismatch) and try to inject semicolon and drop statement, prepared statement would treat injection as literal value and thsus be safe. eg:
var preparedstatement = client.query({
text: "select $1::text resulting_att",
values: ['some default'],
name: 'ps_name'}
);
var queryresult = client.query({name: 'ps_name'},["'; DROP TABLE user;"], function(err,res) {
console.log(err,res.rows)
client.end()
});
logs:
null [ anonymous { resulting_att: '\'; DROP TABLE user;' } ]
and not tries to drop anything.

Resources