Как перевести этот запрос с регулярным выражением PostgreSQL (без учета регистра) в запрос ILIKE?

#ruby-on-rails #regex #ruby #postgresql

Вопрос:

У меня есть запрос, который в настоящее время использует PostgreSQL…

 .where("locations.address ~* '#{@street_name}.*#{@street_type}'")
 

Чтобы предотвратить интерпретацию специальных символов при выполнении этого поиска, мне нужно вместо этого использовать запрос ILIKE.

Я не уверен, что делает эта часть запроса и, следовательно, как ее перевести

 .*
 

Может ли кто-нибудь помочь мне понять, как перевести этот запрос в запрос ILIKE, не нарушая порядок построения текущего запроса?

Ответ №1:

В регулярных выражениях . означает «любой символ» и * означает любое количество раз (включая ноль). Следовательно .* , означает строку, содержащую любые символы любой длины.

В Postgres % символ в шаблоне (используется с (I)LIKE ) означает «любая строка из нуля или более символов». (документы)

Поэтому просто замените на .* % при переключении с сопоставления регулярных выражений на сопоставление по шаблону.


Кроме того (не имеет отношения к фактическому вопросу), как правило, очень плохая идея использовать шаблоны строк для создания SQL-запросов, поскольку этот метод подвергает вас атакам с использованием SQL-инъекций. Вместо этого вы должны использовать переменную функциональность вашего ORM. Для ActiveRecord вы можете передать массив значений where , в котором первый элемент является шаблоном инструкции SQL , а последующие элементы являются либо переменными для вставки, либо хэшем именованных переменных для вставки. (документы)

Например:

 .where(["locations.address ILIKE ? || '%' || ?", street_name, street_type])
 

или

 .where(["locations.address ILIKE :street_name || '%' || :street_type", {street_name: street_name, street_type: street_type}])
 

Комментарии:

1. Спасибо Генри — для того, чтобы использовать ILIKE вместо ~* будет ли это работать: .where(["locations.address ILIKE ? || '.*' || ?", street_name, street_type]) ?

2. @BenRichardson, если вы поменяетесь .* местами с % ним, должно быть.