diff --git a/app/models/query.rb b/app/models/query.rb index 641c0d17b..d9a720812 100644 --- a/app/models/query.rb +++ b/app/models/query.rb @@ -125,7 +125,7 @@ class Query < ActiveRecord::Base filters.each_key do |field| errors.add label_for(field), :activerecord_error_blank unless # filter requires one or more values - (values_for(field) and !values_for(field).first.empty?) or + (values_for(field) and !values_for(field).first.blank?) or # filter doesn't require any value ["o", "c", "!*", "*", "t", "w"].include? operator_for(field) end if filters @@ -296,11 +296,13 @@ class Query < ActiveRecord::Base v = values_for(field).clone next unless v and !v.empty? - sql = '' + sql = '' + is_custom_filter = false if field =~ /^cf_(\d+)$/ # custom field db_table = CustomValue.table_name db_field = 'value' + is_custom_filter = true sql << "#{Issue.table_name}.id IN (SELECT #{Issue.table_name}.id FROM #{Issue.table_name} LEFT OUTER JOIN #{db_table} ON #{db_table}.customized_type='Issue' AND #{db_table}.customized_id=#{Issue.table_name}.id AND #{db_table}.custom_field_id=#{$1} WHERE " else # regular field @@ -320,9 +322,11 @@ class Query < ActiveRecord::Base when "!" sql = sql + "(#{db_table}.#{db_field} IS NULL OR #{db_table}.#{db_field} NOT IN (" + v.collect{|val| "'#{connection.quote_string(val)}'"}.join(",") + "))" when "!*" - sql = sql + "#{db_table}.#{db_field} IS NULL OR #{db_table}.#{db_field} = ''" + sql = sql + "#{db_table}.#{db_field} IS NULL" + sql << " OR #{db_table}.#{db_field} = ''" if is_custom_filter when "*" - sql = sql + "#{db_table}.#{db_field} IS NOT NULL AND #{db_table}.#{db_field} <> ''" + sql = sql + "#{db_table}.#{db_field} IS NOT NULL" + sql << " AND #{db_table}.#{db_field} <> ''" if is_custom_filter when ">=" sql = sql + "#{db_table}.#{db_field} >= #{v.first.to_i}" when "<=" diff --git a/test/fixtures/custom_fields.yml b/test/fixtures/custom_fields.yml index 6be840fcc..3a9e79a29 100644 --- a/test/fixtures/custom_fields.yml +++ b/test/fixtures/custom_fields.yml @@ -4,6 +4,7 @@ custom_fields_001: min_length: 0 regexp: "" is_for_all: true + is_filter: true type: IssueCustomField max_length: 0 possible_values: MySQL|PostgreSQL|Oracle diff --git a/test/unit/query_test.rb b/test/unit/query_test.rb index d291018fb..e143e6fc2 100644 --- a/test/unit/query_test.rb +++ b/test/unit/query_test.rb @@ -29,6 +29,80 @@ class QueryTest < Test::Unit::TestCase assert_equal Issue.find(3), issues.first end + def test_operator_none + query = Query.new(:project => Project.find(1), :name => '_') + query.add_filter('fixed_version_id', '!*', ['']) + query.add_filter('cf_1', '!*', ['']) + assert query.statement.include?("#{Issue.table_name}.fixed_version_id IS NULL") + assert query.statement.include?("#{CustomValue.table_name}.value IS NULL OR #{CustomValue.table_name}.value = ''") + issues = Issue.find :all,:include => [ :assigned_to, :status, :tracker, :project, :priority ], :conditions => query.statement + end + + def test_operator_all + query = Query.new(:project => Project.find(1), :name => '_') + query.add_filter('fixed_version_id', '*', ['']) + query.add_filter('cf_1', '*', ['']) + assert query.statement.include?("#{Issue.table_name}.fixed_version_id IS NOT NULL") + assert query.statement.include?("#{CustomValue.table_name}.value IS NOT NULL AND #{CustomValue.table_name}.value <> ''") + issues = Issue.find :all,:include => [ :assigned_to, :status, :tracker, :project, :priority ], :conditions => query.statement + end + + def test_operator_greater_than + query = Query.new(:project => Project.find(1), :name => '_') + query.add_filter('done_ratio', '>=', ['40']) + assert query.statement.include?("#{Issue.table_name}.done_ratio >= 40") + issues = Issue.find :all,:include => [ :assigned_to, :status, :tracker, :project, :priority ], :conditions => query.statement + end + + def test_operator_in_more_than + query = Query.new(:project => Project.find(1), :name => '_') + query.add_filter('due_date', '>t+', ['15']) + assert query.statement.include?("#{Issue.table_name}.due_date >=") + issues = Issue.find :all,:include => [ :assigned_to, :status, :tracker, :project, :priority ], :conditions => query.statement + end + + def test_operator_in_less_than + query = Query.new(:project => Project.find(1), :name => '_') + query.add_filter('due_date', ' [ :assigned_to, :status, :tracker, :project, :priority ], :conditions => query.statement + end + + def test_operator_today + query = Query.new(:project => Project.find(1), :name => '_') + query.add_filter('due_date', 't', ['']) + assert query.statement.include?("#{Issue.table_name}.due_date BETWEEN") + issues = Issue.find :all,:include => [ :assigned_to, :status, :tracker, :project, :priority ], :conditions => query.statement + end + + def test_operator_this_week_on_date + query = Query.new(:project => Project.find(1), :name => '_') + query.add_filter('due_date', 'w', ['']) + assert query.statement.include?("#{Issue.table_name}.due_date BETWEEN") + issues = Issue.find :all,:include => [ :assigned_to, :status, :tracker, :project, :priority ], :conditions => query.statement + end + + def test_operator_this_week_on_datetime + query = Query.new(:project => Project.find(1), :name => '_') + query.add_filter('created_on', 'w', ['']) + assert query.statement.include?("#{Issue.table_name}.created_on BETWEEN") + issues = Issue.find :all,:include => [ :assigned_to, :status, :tracker, :project, :priority ], :conditions => query.statement + end + + def test_operator_contains + query = Query.new(:project => Project.find(1), :name => '_') + query.add_filter('subject', '~', ['string']) + assert query.statement.include?("#{Issue.table_name}.subject LIKE '%string%'") + issues = Issue.find :all,:include => [ :assigned_to, :status, :tracker, :project, :priority ], :conditions => query.statement + end + + def test_operator_does_not_contains + query = Query.new(:project => Project.find(1), :name => '_') + query.add_filter('subject', '!~', ['string']) + assert query.statement.include?("#{Issue.table_name}.subject NOT LIKE '%string%'") + issues = Issue.find :all,:include => [ :assigned_to, :status, :tracker, :project, :priority ], :conditions => query.statement + end + def test_default_columns q = Query.new assert !q.columns.empty?