Commit d4eea275 authored by Douwe Maan's avatar Douwe Maan

Modify fuzzy_arel_match to search for equality when a term shorter than 3 characters is provided

parent b2c5363d
...@@ -4,7 +4,7 @@ module Gitlab ...@@ -4,7 +4,7 @@ module Gitlab
extend ActiveSupport::Concern extend ActiveSupport::Concern
MIN_CHARS_FOR_PARTIAL_MATCHING = 3 MIN_CHARS_FOR_PARTIAL_MATCHING = 3
REGEX_QUOTED_WORD = /(?<=^| )"[^"]+"(?= |$)/ REGEX_QUOTED_WORD = /(?<=\A| )"[^"]+"(?= |\z)/
class_methods do class_methods do
def to_pattern(query) def to_pattern(query)
...@@ -20,11 +20,18 @@ module Gitlab ...@@ -20,11 +20,18 @@ module Gitlab
end end
def fuzzy_arel_match(column, query) def fuzzy_arel_match(column, query)
words = select_fuzzy_words(query) query = query.squish
return nil unless query.present?
matches = words.map { |word| arel_table[column].matches(to_pattern(word)) } words = select_fuzzy_words(query)
matches.reduce { |result, match| result.and(match) } if words.any?
words.map { |word| arel_table[column].matches(to_pattern(word)) }.reduce(:and)
else
# No words of at least 3 chars, but we can search for an exact
# case insensitive match with the query as a whole
arel_table[column].matches(sanitize_sql_like(query))
end
end end
def select_fuzzy_words(query) def select_fuzzy_words(query)
...@@ -32,7 +39,7 @@ module Gitlab ...@@ -32,7 +39,7 @@ module Gitlab
query = quoted_words.reduce(query) { |q, quoted_word| q.sub(quoted_word, '') } query = quoted_words.reduce(query) { |q, quoted_word| q.sub(quoted_word, '') }
words = query.split(/\s+/) words = query.split
quoted_words.map! { |quoted_word| quoted_word[1..-2] } quoted_words.map! { |quoted_word| quoted_word[1..-2] }
......
...@@ -151,8 +151,8 @@ describe Gitlab::SQL::Pattern do ...@@ -151,8 +151,8 @@ describe Gitlab::SQL::Pattern do
context 'with a word shorter than 3 chars' do context 'with a word shorter than 3 chars' do
let(:query) { 'fo' } let(:query) { 'fo' }
it 'returns nil' do it 'returns a single equality condition' do
expect(fuzzy_arel_match).to be_nil expect(fuzzy_arel_match.to_sql).to match(/title.*I?LIKE 'fo'/)
end end
end end
...@@ -164,6 +164,22 @@ describe Gitlab::SQL::Pattern do ...@@ -164,6 +164,22 @@ describe Gitlab::SQL::Pattern do
end end
end end
context 'with two words both shorter than 3 chars' do
let(:query) { 'fo ba' }
it 'returns a single ILIKE condition' do
expect(fuzzy_arel_match.to_sql).to match(/title.*I?LIKE 'fo ba'/)
end
end
context 'with two words, one shorter 3 chars' do
let(:query) { 'foo ba' }
it 'returns a single ILIKE condition using the longer word' do
expect(fuzzy_arel_match.to_sql).to match(/title.+I?LIKE '\%foo\%'/)
end
end
context 'with a multi-word surrounded by double quote and two words' do context 'with a multi-word surrounded by double quote and two words' do
let(:query) { 'foo "really bar" baz' } let(:query) { 'foo "really bar" baz' }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment