Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I escape % in Knex where like query?

I'm using knex to generate my SQL queries. In knex documentation, it shows this

knex('users').where('columnName', 'like', '%rowlikeme%')

Now in my application, I did this:

function search(term) {
  term = "%" + term + "%";
  knex('table').where('description', 'like', term);
  // ...
}

How can I escape % so that it searches for % as part of the term as well?

Thanks.

like image 557
Jun Avatar asked May 14 '18 09:05

Jun


People also ask

What does KNEX Select Return?

Knex returns an array for all queries, even if there is only one row returned. const user = knex.select('name').from('users').where('id', 1) The name of the user can be accessed from user[0] .

What is KNEX query?

Knex.js (pronounced /kəˈnɛks/) is a "batteries included" SQL query builder for PostgreSQL, CockroachDB, MSSQL, MySQL, MariaDB, SQLite3, Better-SQLite3, Oracle, and Amazon Redshift designed to be flexible, portable, and fun to use.

Is KNEX an ORM?

Sequelize is an ORM that includes some query builder stuff; Knex is just a query builder, not an ORM.

What is a KNEX schema?

The knex. schema is a getter function, which returns a stateful object containing the query. Therefore be sure to obtain a new instance of the knex. schema for every query.


Video Answer


3 Answers

For this case I use

rather string interpolation from es6 (safe version)

knex('table').where('description', 'like', `%${term}%`)

or ?? parameter binding

knex('table').whereRaw('description like \'%??%\'', [term])

But in the first case, you must be 100% sure that term is valid, because of the possibility of SQL injection.

like image 196
coockoo Avatar answered Oct 07 '22 00:10

coockoo


So I was looking for a correct way to apply LOWER function to the parameter. Here's the solution that seems to be working fine for me:

builder.whereRaw('LOWER(last_name) LIKE LOWER(?)', [`%${lastName}%`])
like image 26
Andrew Kicha Avatar answered Oct 06 '22 22:10

Andrew Kicha


@coockoo's answer is incorrect for both of the SQLs. Their first one would still allow % through as Knex does not escape % for LIKE operations. The second SQL simply does not work as Knex wraps the bound value with quotes.

The correct way should be

const term = '10%'
const b = knex('table').where('description', 'like', `%${term.replaceAll('%', '\\%')}%`)

The output of b.toString() is:

select * from "table" where "description" like E'%10\\%%'

Postgres will interpret E'\\%' as '\%', which is an escaped percentage sign according to: https://www.postgresql.org/docs/current/functions-matching.html#FUNCTIONS-LIKE by default if you are on newer Postgres version.


This can be verified with this table:

CREATE TABLE test (
    description character varying(256)
);

INSERT INTO test VALUES ('a%b');

and test the following:

  1. Without escaping % like others have suggested. This shouldn't work.
knex('test').where('description', 'like', 'a%%%b').toString()
select * from "test" where "description" like 'a%%%b'
 description
-------------
 a%b
(1 row)
  1. Escaping % before giving to Knex.

    1. This should return no rows:
    knex('test').where('description', 'like', 'a\\%\\%\\%b').toString()
    
    select * from "test" where "description" like E'a\\%\\%\\%b'
    
     description
    -------------
    (0 rows)
    
    1. This should return 'a%b':
    knex('test').where('description', 'like', 'a\\%b').toString()
    
    select * from "test" where "description" like E'a\\%b'
    
     description
    -------------
     a%b
    (1 row)
    

SQL Fiddle: http://sqlfiddle.com/#!17/d2f5e/1

like image 2
Daniel Cheung Avatar answered Oct 06 '22 23:10

Daniel Cheung