24

I used to name my parameters in my SQL query when preparing it for practical reasons like in php with PDO.

So can I use named parameters with node-postgres module?

For now, I saw many examples and docs on internet showing queries like so:

client.query("SELECT * FROM foo WHERE id = $1 AND color = $2", [22, 'blue']);

But is this also correct?

client.query("SELECT * FROM foo WHERE id = :id AND color = :color", {id: 22, color: 'blue'});

or this

client.query("SELECT * FROM foo WHERE id = ? AND color = ?", [22, 'blue']);

I'm asking this because of the numbered parameter $n that doesn't help me in the case of queries built dynamically.

2

4 Answers 4

10

There is a library for what you are trying to do. Here's how:

var sql = require('yesql').pg

client.query(sql("SELECT * FROM foo WHERE id = :id AND color = :color")({id: 22, color: 'blue'}));
Sign up to request clarification or add additional context in comments.

2 Comments

At least, seems to be a fresh solution one year later! I'll give it a try asap and let you know.Thanks :)
Great lib, but I prefer answers to SO answers that are based on first principles (don't require libraries), with a mention of the lib for reference in case OP wants that.
8

QueryConvert to the rescue. It will take a parameterized sql string and an object and converts it to pg conforming query config.

type QueryReducerArray = [string, any[], number];
export function queryConvert(parameterizedSql: string, params: Dict<any>) {
    const [text, values] = Object.entries(params).reduce(
        ([sql, array, index], [key, value]) => [sql.replace(`:${key}`, `$${index}`), [...array, value], index + 1] as QueryReducerArray,
        [parameterizedSql, [], 1] as QueryReducerArray
    );
    return { text, values };
}

Usage would be as follows:

client.query(queryConvert("SELECT * FROM foo WHERE id = :id AND color = :color", {id: 22, color: 'blue'}));

6 Comments

Thank you! Good util function, no need to use library for this
@ArtemKolodko please also see my latest answer below. Which I think is even neater :)
I get: Cannot find name 'Dict'. What imports are necessary for this to be recognized?
Hi @andymel it is a custom type I find to be handy: interface Dict<T> { [Key: string]: T }
Does this introduce any risk of SQL Injection? I don't know for certain, but I think passing the values in the 2nd arg array does some sort of cleanse under the hood to prevent interpolation being used as an avenue for attack.
|
-1

I have been working with nodejs and postgres. I usually execute queries like this:

client.query("DELETE FROM vehiculo WHERE vehiculo_id= $1", [id], function (err, result){ //Delete a record in de db
    if(err){
        client.end();//Close de data base conection
      //Error code here
    }
    else{
      client.end();
      //Some code here
    }
  });

1 Comment

Yeah, I omit callback but there is still the problem.
-1

Not exactly what the OP is asking for. But you could also use:

import SQL from 'sql-template-strings';

client.query(SQL`SELECT * FROM unicorn WHERE color = ${colorName}`)

It uses tag functions in combination with template literals to embed the values

5 Comments

will this prevent sql injection?
Yes, that is the purpose of sql-template-strings
Feel dangerous as hell, injecting raw values like this and sanitizing it on the library level. As least fi I understood correctly.
dunno, you always have to trust functions at some point of time. But of course it is easier for an junior to remove SQL from the beginning of the string and missing it in a code review. Than probably my top voted function is a better fit for you.
It's not sanitized at the library level, the library just converts this to { text: 'SELECT * FROM unicorn WHERE color = $1', values: [colorName] }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.