summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouwe Maan <douwe@selenight.nl>2017-11-24 12:23:47 +0100
committerDouwe Maan <douwe@selenight.nl>2017-11-27 11:29:40 +0100
commitd4eea275310867eccc927d0e92a1d19a165f0668 (patch)
tree2909c3b95d69aadfd6dba5a3d9f2e18132960db8
parentb2c5363da1bdfb4df8693de38f9d83fe203e6e99 (diff)
downloadgitlab-ce-d4eea275310867eccc927d0e92a1d19a165f0668.tar.gz
Modify fuzzy_arel_match to search for equality when a term shorter than 3 characters is provided
-rw-r--r--lib/gitlab/sql/pattern.rb17
-rw-r--r--spec/lib/gitlab/sql/pattern_spec.rb20
2 files changed, 30 insertions, 7 deletions
diff --git a/lib/gitlab/sql/pattern.rb b/lib/gitlab/sql/pattern.rb
index 8741aa0f1c4..20ca36efb29 100644
--- a/lib/gitlab/sql/pattern.rb
+++ b/lib/gitlab/sql/pattern.rb
@@ -4,7 +4,7 @@ module Gitlab
extend ActiveSupport::Concern
MIN_CHARS_FOR_PARTIAL_MATCHING = 3
- REGEX_QUOTED_WORD = /(?<=^| )"[^"]+"(?= |$)/
+ REGEX_QUOTED_WORD = /(?<=\A| )"[^"]+"(?= |\z)/
class_methods do
def to_pattern(query)
@@ -20,11 +20,18 @@ module Gitlab
end
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
def select_fuzzy_words(query)
@@ -32,7 +39,7 @@ module Gitlab
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] }
diff --git a/spec/lib/gitlab/sql/pattern_spec.rb b/spec/lib/gitlab/sql/pattern_spec.rb
index d2989489e49..ef51e3cc8df 100644
--- a/spec/lib/gitlab/sql/pattern_spec.rb
+++ b/spec/lib/gitlab/sql/pattern_spec.rb
@@ -151,8 +151,8 @@ describe Gitlab::SQL::Pattern do
context 'with a word shorter than 3 chars' do
let(:query) { 'fo' }
- it 'returns nil' do
- expect(fuzzy_arel_match).to be_nil
+ it 'returns a single equality condition' do
+ expect(fuzzy_arel_match.to_sql).to match(/title.*I?LIKE 'fo'/)
end
end
@@ -164,6 +164,22 @@ describe Gitlab::SQL::Pattern do
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
let(:query) { 'foo "really bar" baz' }