Reputation: 159
I am trying to dynamically change the column queried in a WHERE statement.
My code looks like this
const pg = require('pg');
const pool = new pg.Pool();
await pool.connect();
let selector = {
key: 'foo',
value: 'bar',
};
const result = await pool.query(`SELECT * FROM foobar WHERE ${selector.key}=$1::text`, [selector.value]);
There is only a few key values I switch between. While the key is pre-defined and not from user input I would prefer not to use a template string.
Is there a way to parameterize the column name?
I have tried a few ways.
await pool.query('SELECT * FROM foobar WHERE $1=$2::text', [selector.key, selector.value]);
This doesn't work as it parameterizes the key as a string so is just doing a string comparison.
oid
(this was mentioned somewhere but I can't remember where)await pool.query('SELECT * FROM foobar WHERE $1::oid=$2::text', [selector.key, selector.value]);
This throws an error as pg doesn't have a way to cast text to oid
.
Upvotes: 0
Views: 1169
Reputation: 797
As previous answers state: column names cannot be used in parameterized queries, they need to be specified in the SQL string. To escape any potential injections I used:
import { Client, Pool } from 'pg';
const { escapeIdentifier } = new Client();
const pool = new Pool({ /*config here*/ });
const columnName = 'id';
const userId = 'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11';
const result = pool.query(
`SELECT * FROM users WHERE ${escapeIdentifier(columnName)} = $1`,
[userId]
);
Source: https://node-postgres.com/apis/utilities#pgescapeidentifier
Upvotes: 1
Reputation: 2454
Plpgsql could be a possible solution. Consider the following function:
CREATE OR REPLACE FUNCTION run_prepared_on_foobar(q text) RETURNS foobar AS $$
DECLARE
retval foobar;
BEGIN
EXECUTE q INTO retval;
RETURN retval;
END $$ LANGUAGE plpgsql;
Once this is in place, you can then call it by passing any prepared statement:
SELECT * FROM run_prepared_on_foobar('SELECT * FROM foobar WHERE '||$1::text||'='||$2::int)
This is extremely poor in performance since the planner will not be able to peek inside what is going on in the function. All estimates will be random.
Shenanigans of plpgsql aside, a better approach would be to have extra code to switch over different queries depending on external conditions.
Upvotes: 1