Quellcode durchsuchen

OR search with multiple terms for "starts with" and "ends with" filter operators (#38456).

Patch by Go MAEDA.


git-svn-id: https://svn.redmine.org/redmine/trunk@22202 e93f8b46-1217-0410-a6f0-8f06a7374b81
tags/5.1.0
Go MAEDA vor 1 Jahr
Ursprung
Commit
0e19e183b1
2 geänderte Dateien mit 45 neuen und 15 gelöschten Zeilen
  1. 17
    15
      app/models/query.rb
  2. 28
    0
      test/unit/query_test.rb

+ 17
- 15
app/models/query.rb Datei anzeigen

@@ -1452,31 +1452,33 @@ class Query < ActiveRecord::Base
# * :starts_with - use LIKE 'value%' if true
# * :ends_with - use LIKE '%value' if true
# * :all_words - use OR instead of AND if false
# (ignored if :starts_with or :ends_with is true)
def sql_contains(db_field, value, options={})
options = {} unless options.is_a?(Hash)
options.symbolize_keys!
prefix = suffix = nil
prefix = '%' if options[:ends_with]
suffix = '%' if options[:starts_with]
if prefix || suffix
value = queried_class.sanitize_sql_like value
queried_class.sanitize_sql_for_conditions(
[Redmine::Database.like(db_field, '?', :match => options[:match]), "#{prefix}#{value}#{suffix}"]
)
else
queried_class.sanitize_sql_for_conditions(
::Query.tokenized_like_conditions(db_field, value, **options)
)
end
queried_class.sanitize_sql_for_conditions(
::Query.tokenized_like_conditions(db_field, value, **options)
)
end

# rubocop:disable Lint/IneffectiveAccessModifier
def self.tokenized_like_conditions(db_field, value, **options)
tokens = Redmine::Search::Tokenizer.new(value).tokens
tokens = [value] unless tokens.present?
logical_opr = options.delete(:all_words) == false ? ' OR ' : ' AND '

if options[:starts_with]
prefix, suffix = nil, '%'
logical_opr = ' OR '
elsif options[:ends_with]
prefix, suffix = '%', nil
logical_opr = ' OR '
else
prefix = suffix = '%'
logical_opr = options[:all_words] == false ? ' OR ' : ' AND '
end

sql, values = tokens.map do |token|
[Redmine::Database.like(db_field, '?', options), "%#{sanitize_sql_like token}%"]
[Redmine::Database.like(db_field, '?', options), "#{prefix}#{sanitize_sql_like token}#{suffix}"]
end.transpose
[sql.join(logical_opr), *values]
end

+ 28
- 0
test/unit/query_test.rb Datei anzeigen

@@ -3086,6 +3086,34 @@ class QueryTest < ActiveSupport::TestCase
assert_equal 1, query.issue_count
end

def test_sql_contains_should_tokenize_for_starts_with
query = IssueQuery.new(
:project => nil, :name => '_',
:filters => {
'subject' => {:operator => '^', :values => ['issue closed']}
}
)

assert_equal 4, query.issue_count
query.issues.each do |issue|
assert_match /^(issue|closed)/i, issue.subject
end
end

def test_sql_contains_should_tokenize_for_ends_with
query = IssueQuery.new(
:project => nil, :name => '_',
:filters => {
'subject' => {:operator => '$', :values => ['version issue']}
}
)

assert_equal 4, query.issue_count
query.issues.each do |issue|
assert_match /(version|issue)$/i, issue.subject
end
end

def test_display_type_should_accept_known_types
query = ProjectQuery.new(:name => '_')
query.display_type = 'list'

Laden…
Abbrechen
Speichern