I have a function that inserts a record into a table. The name of the table needs to be a parameter of the function, and the column names are obtained dynamically. To guard against SQL Injection, I would like to use PostgreSQL's parameterized queries. Something like this:
function insert(tableName, val1, val2) {
let qry = `INSERT INTO $1 ($2, $3)
VALUES ($4, $5)
RETURNING id;`
let values = [tableName, 'col1', 'col2', val1, val2]
return db.query(qry, values);
}
While the $n substitution works great for values, it cannot be used for table or column identifiers.
From the PostgreSQL documention
Arguments to the SQL function are referenced in the function body using the syntax $n: $1 refers to the first argument, $2 to the second, and so on. If an argument is of a composite type, then the dot notation, e.g., $1.name, can be used to access attributes of the argument. The arguments can only be used as data values, not as identifiers
Compare this to the following code which works but seems to offer little protection against SQL injection.
(note the use of ECMA6 ${} string substitution in place of parameter substitution)
function insert(tableName, val1, val2) {
let values = ['col1', 'col2', val1, val2]
let qry = `INSERT INTO ${tableName} (${values[0]}, ${values[1]})
VALUES ($3, $4)
RETURNING id;`
return db.query(qry, values);
}
Is there a way to allow parameterized queries that mitigates this? I'm hoping for something built into PostgreSQL or the Postgres library for Node, but I will accept any solid answer.
I'm running Node 9.4 and PostgreSQL 10