Apart from checking that the attributeId is in a list of predefined strings – possible, but in this particular case costly – is there any way to re-write this in a less ‘injectable’ fashion (since the use of '${attributeId}'
is actually a field, and not strictly a parameter…):
const { tablename, attributeId } = req.params;
let stmt = `SELECT DISTINCT row_data->'${attributeId}' as ${attributeId} FROM csv_data WHERE source = '${tablename}'`;
let result;
try {
await pool.connect();
result = await pool.query(stmt);
} catch (err) {
console.error(err);
}
...
return res.status(200).json({
rows: result.rows.map((elt, i, array) => {
return elt[attributeId];
}),
rowCount: result.rowCount,
});
2
Answers
;-) Actually I do want to use dynamic column names, for a very specific purpose, and strangely that wasn't production code so console.error() is fine. But thanks for your concern.
The solution turns out to be pg-format:
Gives me back exactly what I was looking for, as well as handling the escaping:
I definitely don't need the
await pool.connect();
though ;-)You don’t want a prepared statement, you want a parameterised statement:
Also
pool.connect()
if you want to use a one-shot query instead of a client (that you’d later have to release)try
/catch
only around the query, and don’tconsole.error
instead of sending a proper error response