How to set parameterized value in Postgres SELECT query using WHERE condition - node.js

I am very new to PostgreSQL please bear with me.
I need to read records from the table using select query with where condition.
Eg: select * from switch where switchId=10;
QueryFactory.js
let queryMap = {
“getSwitchInfo”: ‘select * from switch where switchId=?’
}
module.exports=queryMap;
Controller.js
let client = require(rootdir+’dao/postgresSQL’);
let queryFactory = require(rootdir+’/dao/QueryFactory’);
let query = queryFactory.getQuery(“getSwitchInfo”);
let switchId = req.query.switchId;
client.query(query, function(err, res){
if(err){
}
});
Please see:- this switchId value 10 I get from client and using query parameter I am getting it in my node backend layer.
Kindly suggest how can I pass switchId to the query as a parameterized value.

I found solution myself for this issue. Added params to an array and passed this array as a second param to client.query method and in the query where condition I added $1. It is working fine now
QueryFactory.js
let queryMap = {
“getSwitchInfo”: ‘select * from switch where switchId=$1’
}
module.exports=queryMap;
Controller.js
let params = [req.query.switchId];
client.query(query, params, function(err, res){
if(err){
}
});

Related

Building a kitchen sink query. Error passing # parameters to SQL Server

Im building a kitchen sink query on NODE, where several parameters, for about 20 tables are being passed. They all form a single SQL Query:
if (data.basics.memberId) { sqlString += ` memberid=#memberId and` };
etc...
Im passing several parameters (about 40), but Im not able to pass the parameters when sending the query to the database:
const pool = await utils.poolPromise
const recordset = await pool.request()
//basics
if (data.basics.memberId) {
.input('memberId', utils.sql.Int, data.basics.memberId)
};
.query(sqlString)
if (recordset.rowsAffected[0] > 0) {
...
...
...
}
and Im getting the error:
Declaration or statement expected.
at
.input('memberId', utils.sql.Int, data.basics.memberId)
and
.query(sqlString)
I've read parameters are not the right way to build dynamic queries, so I thought of using ES6, as
if (data.basics.memberId) { sqlString += ` memberid=${data.basics.memberId} and` };
But I've read that ES6 does not prevent SQL injection on SQL Server.
The question is how do I approach this scenario where the SQL string is variable and changes based on the user selection?
Thanks.
Without a query builder library (e.g. Knex), you'll need to
form the SQL query (as a string)
put the parameters into place
e.g. something like this:
const whereClauses = [];
const inputs = {}; // map input name -> [type, value]
// (1) Process data into WHERE clauses and inputs
if (data.basics.memberId) {
whereClauses.push(`memberid=#memberId`);
inputs.memberId = [utils.sql.Int, data.basics.memberId];
}
if (data.basics.somethingElse) {
whereClauses.push(`somethingElse=#somethingElse`);
inputs.somethingElse = [utils.sql.Int, data.basics.somethingElse];
}
// (etc..., you could use a loop or something for the above)
// (2) Form the final SQL query
const sqlStringBits = ["SELECT * FROM ... WHERE "];
for (let whereClause of whereClauses) {
sqlStringBits.push(whereClause);
sqlStringBits.push("AND");
}
if (whereClauses.length) {
sqlStringBits.pop(); // Remove final AND if we had added one
}
const sqlString = sqlStringBits.join(" ");
// (3) Form the `request` and put the inputs into place
const pool = await utils.poolPromise;
let request = pool.request();
for (let inputName in inputs) {
request = request.input(inputName, ...inputs[inputName]);
}
// (4) Use the request (endowed with inputs) with the query
const recordSet = await request.query(sqlString);
// (5) Do something with the record set!

MongoDB returning a null, but query works separately

In a post function, I am trying to retrieve the nth activity of a user (since I have a dropdown that return the index number of the activity). When I run the query
collection.find({'local.email':req.user.local.email},
{'local.activities':{$slice : [currActivity,1]}});
I receive the correct activity object in Robo3T.
But, when I call the same query in Node inside a post function, it returns an undefined.
app.post('/addlog',function(req,res){
var currActivity = req.body.curAct;
var score = req.body.score;
var comment = req.body.reason;
mongoose.connect('mongodb://****:****#ds044907.mlab.com:44907/intraspect',function (err, database) {
if (err)
throw err
else
{
db = database;
var collection = db.collection('users');
var retrievedAct = collection.find({'local.email':req.user.local.email},
{'local.activities':{$slice : [currActivity,1]}}).toArray().then(console.log(retrievedAct));
if (retrievedAct.length > 0) { printjson (retrievedAct[0]); }
console.log(currActivity);
console.log(retrievedAct[0]);
// console.log(req.body.newAct);
collection.update({'local.activities.name':retrievedAct[0]},
{$push: {'local.activities.log' : {
comments: comment,
score: score,
log_time: Date.now()
}}})
.then(function(){
res.redirect('/homepage');
})
.catch(function() {
console.log('Error');
});
}
});
});
I checked that the currActivity variable does infact contain the integer value for the nth activity.
If you want the result of collection.find().toArray(), as specified in the docs, you have two options:
Passing a callback to .toArray() like you did with mongoose.connect()
Using the Promise that it returns if you don't pass a callback
Now you are doing neither of them.
Also, you are mixing callback style and Promises in your code. I recommend you unificate your code. If you are using a Node.js version bigger than 8, using async/await could be nice, it makes it simpler.

Mysql inserts with AWS Lambda + Node.js

I'm running nodejs function in Amazon Lambda. It is supposed to do an insert to mysql DB after a HTTP get. Everything seems to be fine -- looking at the cloudwatch logs the query is parsed correctly and if I copy paste the query to mysql console it does exactly what it is supposed to.
Essentially:
var mysql = require('mysql')
var connection = createConnection({ connection details });
connection.connect();
var query = connection.query('Insert into AAA select * \
from BBB where BBB.a = ?;', [parameter],
function(err, result) {}
);
connection.end();
The problems is that the Lambda version simply does nothing. Query is visible and correct and the function returns cleanly but it never actually inserts anything. I have the same problem with update query as well but all the mysql selects work and return stuff so the problem is not that. The insert also works when I run it on my machine -- when I push it to lambda the problem appears.
I tried to add a separate commit statement but couldn't get it working either. I'm clearly missing something but can't figure out what. Do I need to have a transaction block for updates?
EDIT: Per Mark B's request. I think I tried to be smarter than I am by showing only part of the code. The whole logic was:
exports.handler = function(event, context, callback){
if ( event.A == -1 ){
exports.updateDB(event, function(res) {
context.succeed(res)
}
}
};
exports.updateDB = function(event, callback) {
var mysql = require('mysql')
var connection = createConnection({ connection details });
connection.connect();
var query = connection.query( 'update products set A=? where product_id = ?;',
[parameters],
function(err,result){ });
var query = connection.query( 'insert into other_table select * from products where product_id = ?;',
[parameters],
function(err,result){ });
connection.commit(function(err) {
if(err) {
connection.rollback(function() {
throw(err);
});
}
connection.end();
});
callback({"ok":"ok"})
};
Per advice given here I made the following changes. I took the last callback away, and did put callbacks inside both connection.queries:
var query = connection.query( 'insert into other_table select * from products where product_id = ?;',
[parameters],
function(err,result){
callback({"ok":"ok"})
});
And it seems to work. I'm guessing now that the commit -part does nothing but it doesn't seem to break it either. It probably is obvious at this point that I'm not much of a developer and even less so familiar with node.js so I truly appreciate the help I got!
Please note that the query function is an asynchronous function, meaning that it will be no result available until the callback function is triggered. In your sample code, the connection is closed immediately after it was triggered, long before the callback is executed. Try changing the code so that connection is closed by in the callback function, e.g.
var query = connection.query('Insert into AAA select * \
from BBB where BBB.a = ?;', [parameter],
function(err, result) {
// now it is ok to close the connection
connection.end();
if (err) {
// error handling
}
else {
// do something with the result
}
}
);
By the way, since you are working with Lambda, the same thing applies to the callback(), context.succeed() and context.fail() function handlers. In other words, it is likely that you would like to call them where I wrote the comments about error and result handling above.

Run Sequelize raw query for each result of another sequelize query

i am using sequelize.js in node app to fetch data from a query and then run another sequelize raw query for each result element. but dude to callbacks i am not getting results.
my code:
var raw_query1 = "select id,name,has_results from users";
sequelize.query(raw_query1).then(function(results) {
var outputArray = []; // to store use results with additional results
for(i=0;i<results.length;i++){
outputArray[i].name = results[i].name;
var raw_query2 = "select * from meta where user_id = "+resulsts[i].id;
sequelize.query(raw_query2).then(function(meta_results) {
outputArray[i].meta = meta_results;
}
}
return res.json(outputArray); //Returning parsed results
});
i think we need to use promise here but i am a newbie from php and dont know how to proceed thanks in advance.
You need to use bluebird.map.
var raw_query1 = "select id,name,has_results from users";
sequelize.query(raw_query1).then(function(results) {
return bluebird.map(results, function(user){
var raw_query2 = "select * from meta where user_id = "+user.id;
return sequelize.query(raw_query2)
})
.then(function(metas){
return res.json(metas);
});
});

NodeJS get values from SQL query

I have https://www.npmjs.org/package/mysql module.
They show examples how to use it when multiple rows are expected, but I couldn't find one example showing how to fetch a single result into a variable.
SELECT name FROM users WHERE id=1 LIMIT 1
how do I fetch this into sqlValues variable ?
In the callback function of the .query method, the second parameter contains an array containing the rows returned from your query. No matter how many are returned, these can be indexed just as an array.
Thus, in the callback function to get the single expected result, you can use rows[0].
In your specific instance, to assign the returned name field to the sqlValues variable, you can use a simple assignment: sqlValues = rows[0].name
You can see the code below which connects to sql and fetches data.
var mysql = require('mysql');
var connection = mysql.createConnection(
{
host : 'localhost',
user : 'your-username',
password : 'your-password',
database : 'wordpress',
}
);
connection.connect();
var queryString = 'SELECT name FROM users WHERE id=1 LIMIT 1';
connection.query(queryString, function(err, rows, fields) {
if (err) throw err;
for (var i in rows) {
console.log('Post Titles: ', rows[i].yourcolumnname);
}
});
connection.end();
you can implement this code like this … (more simple)
var queryString = 'SELECT name FROM users WHERE id=1 LIMIT 1';
connection.query(queryString, function(err, rows) {
if (err) throw err
res.send(rows)
console.log(rows)//this
});
connection.end();

Resources