@@ -115,7 +115,8 class Query < ActiveRecord::Base | |||||
115 | "~" => :label_contains, |
|
115 | "~" => :label_contains, | |
116 | "!~" => :label_not_contains, |
|
116 | "!~" => :label_not_contains, | |
117 | "=p" => :label_any_issues_in_project, |
|
117 | "=p" => :label_any_issues_in_project, | |
118 |
"=!p" => :label_any_issues_not_in_project |
|
118 | "=!p" => :label_any_issues_not_in_project, | |
|
119 | "!p" => :label_no_issues_in_project} | |||
119 |
|
120 | |||
120 | cattr_reader :operators |
|
121 | cattr_reader :operators | |
121 |
|
122 | |||
@@ -129,7 +130,7 class Query < ActiveRecord::Base | |||||
129 | :text => [ "~", "!~", "!*", "*" ], |
|
130 | :text => [ "~", "!~", "!*", "*" ], | |
130 | :integer => [ "=", ">=", "<=", "><", "!*", "*" ], |
|
131 | :integer => [ "=", ">=", "<=", "><", "!*", "*" ], | |
131 | :float => [ "=", ">=", "<=", "><", "!*", "*" ], |
|
132 | :float => [ "=", ">=", "<=", "><", "!*", "*" ], | |
132 | :relation => ["=", "=p", "=!p", "!*", "*"]} |
|
133 | :relation => ["=", "=p", "=!p", "!p", "!*", "*"]} | |
133 |
|
134 | |||
134 | cattr_reader :operators_by_filter_type |
|
135 | cattr_reader :operators_by_filter_type | |
135 |
|
136 | |||
@@ -807,14 +808,15 class Query < ActiveRecord::Base | |||||
807 | when "=", "!" |
|
808 | when "=", "!" | |
808 | op = (operator == "=" ? 'IN' : 'NOT IN') |
|
809 | op = (operator == "=" ? 'IN' : 'NOT IN') | |
809 | "#{Issue.table_name}.id #{op} (SELECT DISTINCT #{IssueRelation.table_name}.#{join_column} FROM #{IssueRelation.table_name} WHERE #{IssueRelation.table_name}.relation_type = '#{connection.quote_string(relation_type)}' AND #{IssueRelation.table_name}.#{target_join_column} = #{value.first.to_i})" |
|
810 | "#{Issue.table_name}.id #{op} (SELECT DISTINCT #{IssueRelation.table_name}.#{join_column} FROM #{IssueRelation.table_name} WHERE #{IssueRelation.table_name}.relation_type = '#{connection.quote_string(relation_type)}' AND #{IssueRelation.table_name}.#{target_join_column} = #{value.first.to_i})" | |
810 | when "=p", "=!p" |
|
811 | when "=p", "=!p", "!p" | |
811 |
op = (operator == " |
|
812 | op = (operator == "!p" ? 'NOT IN' : 'IN') | |
812 | "#{Issue.table_name}.id IN (SELECT DISTINCT #{IssueRelation.table_name}.#{join_column} FROM #{IssueRelation.table_name}, #{Issue.table_name} relissues WHERE #{IssueRelation.table_name}.relation_type = '#{connection.quote_string(relation_type)}' AND #{IssueRelation.table_name}.#{target_join_column} = relissues.id AND relissues.project_id #{op} #{value.first.to_i})" |
|
813 | comp = (operator == "=!p" ? '<>' : '=') | |
|
814 | "#{Issue.table_name}.id #{op} (SELECT DISTINCT #{IssueRelation.table_name}.#{join_column} FROM #{IssueRelation.table_name}, #{Issue.table_name} relissues WHERE #{IssueRelation.table_name}.relation_type = '#{connection.quote_string(relation_type)}' AND #{IssueRelation.table_name}.#{target_join_column} = relissues.id AND relissues.project_id #{comp} #{value.first.to_i})" | |||
813 | end |
|
815 | end | |
814 |
|
816 | |||
815 | if relation_options[:sym] == field && !options[:reverse] |
|
817 | if relation_options[:sym] == field && !options[:reverse] | |
816 | sqls = [sql, sql_for_relations(field, operator, value, :reverse => true)] |
|
818 | sqls = [sql, sql_for_relations(field, operator, value, :reverse => true)] | |
817 | sqls.join(["!", "!*"].include?(operator) ? " AND " : " OR ") |
|
819 | sqls.join(["!", "!*", "!p"].include?(operator) ? " AND " : " OR ") | |
818 | else |
|
820 | else | |
819 | sql |
|
821 | sql | |
820 | end |
|
822 | end |
@@ -674,6 +674,7 en: | |||||
674 | label_not_contains: doesn't contain |
|
674 | label_not_contains: doesn't contain | |
675 | label_any_issues_in_project: any issues in project |
|
675 | label_any_issues_in_project: any issues in project | |
676 | label_any_issues_not_in_project: any issues not in project |
|
676 | label_any_issues_not_in_project: any issues not in project | |
|
677 | label_no_issues_in_project: no issues in project | |||
677 | label_day_plural: days |
|
678 | label_day_plural: days | |
678 | label_repository: Repository |
|
679 | label_repository: Repository | |
679 | label_repository_new: New repository |
|
680 | label_repository_new: New repository |
@@ -664,6 +664,7 fr: | |||||
664 | label_not_contains: ne contient pas |
|
664 | label_not_contains: ne contient pas | |
665 | label_any_issues_in_project: une demande du projet |
|
665 | label_any_issues_in_project: une demande du projet | |
666 | label_any_issues_not_in_project: une demande hors du projet |
|
666 | label_any_issues_not_in_project: une demande hors du projet | |
|
667 | label_no_issues_in_project: aucune demande du projet | |||
667 | label_day_plural: jours |
|
668 | label_day_plural: jours | |
668 | label_repository: Dépôt |
|
669 | label_repository: Dépôt | |
669 | label_repository_new: Nouveau dépôt |
|
670 | label_repository_new: Nouveau dépôt |
@@ -260,6 +260,7 function toggleOperator(field) { | |||||
260 | break; |
|
260 | break; | |
261 | case "=p": |
|
261 | case "=p": | |
262 | case "=!p": |
|
262 | case "=!p": | |
|
263 | case "!p": | |||
263 | enableValues(field, [1]); |
|
264 | enableValues(field, [1]); | |
264 | break; |
|
265 | break; | |
265 | default: |
|
266 | default: |
@@ -672,6 +672,22 class QueryTest < ActiveSupport::TestCase | |||||
672 | assert_equal [1], find_issues_with_query(query).map(&:id).sort |
|
672 | assert_equal [1], find_issues_with_query(query).map(&:id).sort | |
673 | end |
|
673 | end | |
674 |
|
674 | |||
|
675 | def test_filter_on_relations_with_no_issues_in_a_project | |||
|
676 | IssueRelation.delete_all | |||
|
677 | with_settings :cross_project_issue_relations => '1' do | |||
|
678 | IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Project.find(2).issues.first) | |||
|
679 | IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(2), :issue_to => Project.find(3).issues.first) | |||
|
680 | IssueRelation.create!(:relation_type => "relates", :issue_to => Project.find(2).issues.first, :issue_from => Issue.find(3)) | |||
|
681 | end | |||
|
682 | ||||
|
683 | query = Query.new(:name => '_') | |||
|
684 | query.filters = {"relates" => {:operator => '!p', :values => ['2']}} | |||
|
685 | ids = find_issues_with_query(query).map(&:id).sort | |||
|
686 | assert_include 2, ids | |||
|
687 | assert_not_include 1, ids | |||
|
688 | assert_not_include 3, ids | |||
|
689 | end | |||
|
690 | ||||
675 | def test_filter_on_relations_with_no_issues |
|
691 | def test_filter_on_relations_with_no_issues | |
676 | IssueRelation.delete_all |
|
692 | IssueRelation.delete_all | |
677 | IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Issue.find(2)) |
|
693 | IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Issue.find(2)) |
General Comments 0
You need to be logged in to leave comments.
Login now