На самом деле это не регулярное выражение, а более простой синтаксический анализатор.
- Это работает путем сопоставления регулярного выражения с начала строки до тех пор, пока оно не встретит пробел, за которым следует либо
and
, либо between
, за которым следует символ пробела. Результат удаляется из where_cause
и сохраняется в statement
.
- Если начало строки теперь начинается с пробела, за которым следует
between
, за которым следует пробел. Он добавляется к statement
и удаляется из where_cause
с чем угодно, что позволяет 1 and
. Сопоставление прекращается, если достигнут конец строки или обнаружен другой and
.
- Если точка 2 не совпадает, проверьте, начинается ли строка с пробела, затем следует
and
, за которым следует пробел. Если это так, удалите это из where_cause
.
- Наконец, добавьте
statement
в массив statements
, если это не пустая строка.
Все сопоставления выполняются без учета регистра.
where_cause = "created_at BETWEEN '2018-01-01T00:00:00+05:30' AND '2019-01-01T00:00:00+05:30' AND updated_at BETWEEN '2018-05-01T00:00:00+05:30' AND '2019-05-01T00:00:00+05:30' AND user_id = 5 AND status = 'closed'"
statements = []
until where_cause.empty?
statement = where_cause.slice!(/\A.*?(?=[\s](and|between)[\s]|\z)/mi)
if where_cause.match? /\A[\s]between[\s]/i
between = /\A[\s]between[\s].*?[\s]and[\s].*?(?=[\s]and[\s]|\z)/mi
statement << where_cause.slice!(between)
elsif where_cause.match? /\A[\s]and[\s]/i
where_cause.slice!(/\A[\s]and[\s]/i)
end
statements << statement unless statement.empty?
end
pp statements
# ["created_at BETWEEN '2018-01-01T00:00:00+05:30' AND '2019-01-01T00:00:00+05:30'",
# "updated_at BETWEEN '2018-05-01T00:00:00+05:30' AND '2019-05-01T00:00:00+05:30'",
# "user_id = 5",
# "status = 'closed'"]
Примечание: Ruby использует \A
для сопоставления начала строки и \z
для сопоставления конца строки вместо обычных ^
и $
, которые соответствуют началу и окончание строки соответственно. См. документацию по привязке регулярного выражения .
Вы можете заменить каждый [\s]
на \s
, если хотите. Я добавил их, чтобы сделать регулярное выражение более читабельным.
Имейте в виду, что это решение не идеально, но может дать вам представление о том, как решить проблему. Причина, по которой я это говорю, заключается в том, что в нем не учитываются слова and
/ between
в имени столбца или в строковом контексте.
Следующее, где причина:
where_cause = "name = 'Tarzan AND Jane'"
Будет выводить:
#=> ["name = 'Tarzan", "Jane'"]
Это решение также предполагает правильно структурированные SQL-запросы. Следующие запросы не приводят к тому, что вы думаете:
where_cause = "created_at = BETWEEN AND"
# TypeError: no implicit conversion of nil into String
# ^ does match /\A[\s]between[\s]/i, but not the #slice! argument
where_cause = "id = BETWEEN 1 AND 2 BETWEEN 1 AND 3"
#=> ["id = BETWEEN 1 AND 2 BETWEEN 1", "3"]