deividy@blog:~

Como usar o node-postgres com query parametrizada #Node.js

12/02/2018

Afim de usar o node-postgres, sem ORM? Ao menos parametrize suas queries! #safetyfirst

Como usar o node-postgres com query parametrizada #Node.js


Em um post anterior, contemplei a beleza de programação funcional, mas nesse post irei mostrar uma das muitas formas da programação orientada a objetos ser muito útil.

Digamos que você não tem um orm, ou simplesmente não quer usar um e decidiu usar o mais próximo possível do nativo. Nesse caso, o mínimo que podemos fazer é usar queries parametrizadas.

Queries parametrizadas (ou consultas parametrizadas, ou parameterized queries, ou ainda prepared statement) são basicamente consultas que escrevemos para o banco de dados com certos códigos para o módulo de acesso ao db pré compilar e nos proteger de algum código malicioso, ou algum tipo de SQL Injection.
Pense em parameterized queries como simplesmente variáveis que você passa para o seu componente de acesso ao banco de dados e ele garante o tipo e protege contra algum escape maldoso.



Com o node-postgres, temos duas formas de fazer isso:

 - 1) Usando apenas COLUMN = $N (onde N é a posição desse argumento em .query(STMT, args1, arg2...)).
 - 2) Passando o COLUMN = $N::TYPE (onde type pode ser text, int, datetime, etc.)



Aqui vamos desenvolver uma classe que irá cuidar de gerar a segunda forma de query pra gente, será algo bem simples e o problema que ela vai resolver é o de termos que lembrar sempre a posição do parâmetro e seu tipo, facilitando nossa escrita de statements.


Sem mais delongas, eis a nossa criança:

class DbArgs { constructor () { this._args = [ ]; } add (value, type) { const argIndex = this._args.length + 1; const fullType = `$${argIndex}::${type}`; this._args.push({ argIndex, type, value, fullType }); return fullType; } toArray () { // values only! return this._args.map((arg) => arg.value); } }

Essa pequena classe simplesmente guarda nossos parâmetros em um array e retorna o text desejado, pronto para usarmos em nosso statemet, de forma que podemos escrever nosso código assim:

const args = new DbArgs(); const stmt = ` SELECT text FROM blog_post WHERE name = ${args.add('%parameterized-query%', 'text')} AND int_test = ${args.add(1, 'int')} AND date = ${args.add(new Date().getTime(), 'timestamp')}; `; const res = client.query(stmt, args.toArray());

Esse código gera o seguinte statement:

SELECT text FROM blog_post WHERE name = $1::text AND int_test = $2::int AND date = $3::timestamp;

E o args.toArray(), retorna:

[ '%parameterized-query%', 1, 1518470278513 ]


Bem mais simples que ter que ficar cuidando de ordem e tipo de argumentos, né? :)




Se curtiu? Comentaaaee!