#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, если вы поменяетесь
.*
местами с%
ним, должно быть.