19

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.

Dharman
  • 30,962
  • 25
  • 85
  • 135
AnomalySmith
  • 597
  • 2
  • 5
  • 16
  • 1
    In [pg-promise](https://github.com/vitaly-t/pg-promise) there is very flexible [Named Parameter formatting](https://github.com/vitaly-t/pg-promise/wiki/Learn-by-Example#named-parameters), even with [Raw-Text formatting](https://github.com/vitaly-t/pg-promise/wiki/Learn-by-Example#raw-text), plus [Custom-Type formatting](https://github.com/vitaly-t/pg-promise#custom-type-formatting). – vitaly-t Sep 16 '15 at 18:26
  • Thanks for the link, I heard about this module but didn't go further. It's what I'm looking for! – AnomalySmith Sep 16 '15 at 21:07

4 Answers4

9

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'}));
pihvi
  • 309
  • 2
  • 5
  • At least, seems to be a fresh solution one year later! I'll give it a try asap and let you know.Thanks :) – AnomalySmith Nov 17 '16 at 09:38
  • 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. – Marc H. Weiner Jan 31 '22 at 20:18
7

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'}));
velop
  • 3,102
  • 1
  • 27
  • 30
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
    }
  });
Kevin Sanchez
  • 2,215
  • 2
  • 11
  • 19
0

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

velop
  • 3,102
  • 1
  • 27
  • 30
  • 2
    will this prevent sql injection? – Novellizator Mar 14 '22 at 11:38
  • 1
    Yes, that is the purpose of sql-template-strings – velop Mar 30 '22 at 07:56
  • 3
    Feel dangerous as hell, injecting raw values like this and sanitizing it on the library level. As least fi I understood correctly. – Novellizator Mar 31 '22 at 13:06
  • 1
    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. – velop Apr 01 '22 at 14:08
  • It's not sanitized at the library level, the library just converts this to `{ text: 'SELECT * FROM unicorn WHERE color = $1', values: [colorName] }` – Jan Aug 19 '22 at 09:27