@@ -779,9 +779,9 class Query < ActiveRecord::Base | |||||
779 | date = Date.today |
|
779 | date = Date.today | |
780 | sql = date_clause(db_table, db_field, date.beginning_of_year, date.end_of_year, is_custom_filter) |
|
780 | sql = date_clause(db_table, db_field, date.beginning_of_year, date.end_of_year, is_custom_filter) | |
781 | when "~" |
|
781 | when "~" | |
782 | sql = "LOWER(#{db_table}.#{db_field}) LIKE '%#{self.class.connection.quote_string(value.first.to_s.downcase)}%'" |
|
782 | sql = sql_contains("#{db_table}.#{db_field}", value.first) | |
783 | when "!~" |
|
783 | when "!~" | |
784 | sql = "LOWER(#{db_table}.#{db_field}) NOT LIKE '%#{self.class.connection.quote_string(value.first.to_s.downcase)}%'" |
|
784 | sql = sql_contains("#{db_table}.#{db_field}", value.first, false) | |
785 | else |
|
785 | else | |
786 | raise "Unknown query operator #{operator}" |
|
786 | raise "Unknown query operator #{operator}" | |
787 | end |
|
787 | end | |
@@ -789,6 +789,12 class Query < ActiveRecord::Base | |||||
789 | return sql |
|
789 | return sql | |
790 | end |
|
790 | end | |
791 |
|
791 | |||
|
792 | # Returns a SQL LIKE statement with wildcards | |||
|
793 | def sql_contains(db_field, value, match=true) | |||
|
794 | value = "'%#{self.class.connection.quote_string(value.to_s)}%'" | |||
|
795 | Redmine::Database.like(db_field, value, :match => match) | |||
|
796 | end | |||
|
797 | ||||
792 | # Adds a filter for the given custom field |
|
798 | # Adds a filter for the given custom field | |
793 | def add_custom_field_filter(field, assoc=nil) |
|
799 | def add_custom_field_filter(field, assoc=nil) | |
794 | options = field.format.query_filter_options(field, self) |
|
800 | options = field.format.query_filter_options(field, self) |
@@ -159,15 +159,7 module Redmine | |||||
159 | private :search_tokens_condition |
|
159 | private :search_tokens_condition | |
160 |
|
160 | |||
161 | def search_token_match_statement(column, value='?') |
|
161 | def search_token_match_statement(column, value='?') | |
162 |
|
|
162 | Redmine::Database.like(column, value) | |
163 | if Redmine::Database.postgresql_unaccent? |
|
|||
164 | "unaccent(#{column}) ILIKE unaccent(#{value})" |
|
|||
165 | else |
|
|||
166 | "#{column} ILIKE #{value}" |
|
|||
167 | end |
|
|||
168 | else |
|
|||
169 | "#{column} LIKE #{value}" |
|
|||
170 | end |
|
|||
171 | end |
|
163 | end | |
172 | private :search_token_match_statement |
|
164 | private :search_token_match_statement | |
173 |
|
165 |
@@ -44,6 +44,21 module Redmine | |||||
44 | end |
|
44 | end | |
45 | end |
|
45 | end | |
46 |
|
46 | |||
|
47 | # Returns a SQL statement for case/accent (if possible) insensitive match | |||
|
48 | def like(left, right, options={}) | |||
|
49 | neg = (options[:match] == false ? 'NOT ' : '') | |||
|
50 | ||||
|
51 | if postgresql? | |||
|
52 | if postgresql_unaccent? | |||
|
53 | "unaccent(#{left}) #{neg}ILIKE unaccent(#{right})" | |||
|
54 | else | |||
|
55 | "#{left} #{neg}ILIKE #{right}" | |||
|
56 | end | |||
|
57 | else | |||
|
58 | "#{left} #{neg}LIKE #{right}" | |||
|
59 | end | |||
|
60 | end | |||
|
61 | ||||
47 | # Resets database information |
|
62 | # Resets database information | |
48 | def reset |
|
63 | def reset | |
49 | @postgresql_unaccent = nil |
|
64 | @postgresql_unaccent = nil |
@@ -592,12 +592,22 class QueryTest < ActiveSupport::TestCase | |||||
592 | end |
|
592 | end | |
593 |
|
593 | |||
594 | def test_operator_contains |
|
594 | def test_operator_contains | |
595 | query = IssueQuery.new(:project => Project.find(1), :name => '_') |
|
595 | issue = Issue.generate!(:subject => 'AbCdEfG') | |
596 | query.add_filter('subject', '~', ['uNable']) |
|
596 | ||
597 | assert query.statement.include?("LOWER(#{Issue.table_name}.subject) LIKE '%unable%'") |
|
597 | query = IssueQuery.new(:name => '_') | |
|
598 | query.add_filter('subject', '~', ['cdeF']) | |||
|
599 | result = find_issues_with_query(query) | |||
|
600 | assert_include issue, result | |||
|
601 | result.each {|issue| assert issue.subject.downcase.include?('cdef') } | |||
|
602 | end | |||
|
603 | ||||
|
604 | def test_operator_does_not_contain | |||
|
605 | issue = Issue.generate!(:subject => 'AbCdEfG') | |||
|
606 | ||||
|
607 | query = IssueQuery.new(:name => '_') | |||
|
608 | query.add_filter('subject', '!~', ['cdeF']) | |||
598 | result = find_issues_with_query(query) |
|
609 | result = find_issues_with_query(query) | |
599 | assert result.empty? |
|
610 | assert_not_include issue, result | |
600 | result.each {|issue| assert issue.subject.downcase.include?('unable') } |
|
|||
601 | end |
|
611 | end | |
602 |
|
612 | |||
603 | def test_range_for_this_week_with_week_starting_on_monday |
|
613 | def test_range_for_this_week_with_week_starting_on_monday | |
@@ -625,13 +635,6 class QueryTest < ActiveSupport::TestCase | |||||
625 | query.statement |
|
635 | query.statement | |
626 | end |
|
636 | end | |
627 |
|
637 | |||
628 | def test_operator_does_not_contains |
|
|||
629 | query = IssueQuery.new(:project => Project.find(1), :name => '_') |
|
|||
630 | query.add_filter('subject', '!~', ['uNable']) |
|
|||
631 | assert query.statement.include?("LOWER(#{Issue.table_name}.subject) NOT LIKE '%unable%'") |
|
|||
632 | find_issues_with_query(query) |
|
|||
633 | end |
|
|||
634 |
|
||||
635 | def test_filter_assigned_to_me |
|
638 | def test_filter_assigned_to_me | |
636 | user = User.find(2) |
|
639 | user = User.find(2) | |
637 | group = Group.find(10) |
|
640 | group = Group.find(10) |
General Comments 0
You need to be logged in to leave comments.
Login now