Skip to content
Advertisement

Knex not properly escaping raw postgres queries

I am using Knex (with typescript) to try to query a postgres database. My database table products has a column name that I want to search through as the user types into a search box. For example, a query of just the letter ‘p’ should return all products with a name that contains a word that begins with ‘p’. For this, I am using the ts_vector and ts_query functions. My query looks like this:

const query = ... // got from user input
const result = await knex(knex.raw('products'))
  .whereRaw(`to_tsvector(name) @@ to_tsquery('?:*')`, query)
  .select('*')

When I run this query, I get the following error:

Unhandled error { error: select * from products where to_tsvector(name) @@ to_tsquery('$1:*') - bind message supplies 1 parameters, but prepared statement "" requires 0

If I replace the whereRaw line with: .whereRaw(`to_tsvector(name) @@ to_tsquery('p:*')`), it correctly runs the query, selecting products whose names contain words beginning with a P.

It seems like there is some conflict with the postgres syntax and knex’s raw queries. I want to use a raw query over using `${query}:*` because I want my inputs to be sanitized and protected from SQL injection. How can I get Knex to properly escape this?

I have tried various combinations of quotes, slashes and colons, but none seem to work. Any help would be appreciated.

Advertisement

Answer

PostgreSQL doesn’t process placeholders when they are inside quotes (and I am a little surprised that knex does).

You need to do the concatenation explicitly, either inside PostgreSQL:

.whereRaw(`to_tsvector(name) @@ to_tsquery(? ||':*')`,query)

Or inside typescript:

.whereRaw(`to_tsvector(name) @@ to_tsquery(?)`, query+":*")
User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement