Rcov report for: lib/query_patch.rb

NameTotal linesLines of codeTotal coverageCode coverage
lib/query_patch.rb244181
27.87%
20.99%
1 # $Id$
2 
3 require 'redmine/version'
4 
5 module RedmineHudson
6   module RedmineExt
7 
8     def RedmineExt.redmine_090_or_higher?
9       return !(Redmine::VERSION::MAJOR == 0 && Redmine::VERSION::MINOR < 9)
10     end
11 
12     module QueryPatch
13       def self.included(base) # :nodoc:
14         base.extend(ClassMethods)
15 
16         base.send(:include, InstanceMethods)
17         base.send(:include, InstanceMethodsFor09Later) if RedmineHudson::RedmineExt.redmine_090_or_higher?
18         base.send(:include, InstanceMethodsFor08) unless RedmineHudson::RedmineExt.redmine_090_or_higher?
19 
20         # Same as typing in the class
21         base.class_eval do
22           unloadable # Send unloadable so it will not be unloaded in development
23 
24           alias_method_chain :available_filters, :redmine_hudson unless method_defined?(:available_filters_without_redmine_hudson)
25           alias_method_chain :sql_for_field, :redmine_hudson unless method_defined?(:sql_for_field_without_redmine_hudson)
26         end
27 
28       end
29     end
30 
31     module ClassMethods
32 
33       unless Query.respond_to?(:available_columns=)
34         # Setter for +available_columns+ that isn't provided by the core.
35         def available_columns=(v)
36           self.available_columns = (v)
37         end
38       end
39 
40       unless Query.respond_to?(:add_available_column)
41         # Method to add a column to the +available_columns+ that isn't provided by the core.
42         def add_available_column(column)
43           self.available_columns << (column)
44         end
45       end
46     end
47 
48     module InstanceMethods
49 
50       def available_filters_with_redmine_hudson
51         return @available_filters if @available_filters
52 
53         available_filters_without_redmine_hudson
54 
55         return @available_filters unless project
56 
57         hudson_filters
58 
59         @hudson_filters.each do |filter|
60           @available_filters[filter.name] = filter.available_values
61         end
62         return @available_filters
63       end
64 
65       def sql_for_hudson_build(field, operator, value)
66         return sql_for_always_false unless project
67 
68         hudson_changesets = find_hudson_changesets
69 
70         return sql_for_issues(hudson_changesets)
71       end
72 
73       def sql_for_hudson_job(field, operator, value)
74         return sql_for_always_false unless project
75 
76         if filters.has_key?('hudson_build')
77           return sql_for_always_true
78         end
79 
80         hudson_changesets = find_hudson_changesets
81 
82         return sql_for_issues(hudson_changesets)
83       end
84 
85       def find_hudson_changesets
86 
87         retval = []
88         find_hudson_jobs.each do |job|
89           builds = find_hudson_builds(job)
90           next if builds.length == 0
91           cond_builds = builds.collect{|build| "#{connection.quote_string(build.id.to_s)}"}.join(",")
92           retval += HudsonBuildChangeset.find(:all, :conditions => ["#{HudsonBuildChangeset.table_name}.hudson_build_id in (#{cond_builds})"], :order => "#{HudsonBuildChangeset.table_name}.id DESC", :limit => Hudson.query_limit_changesets_each_job)
93         end
94 
95         return retval
96 
97       end
98 
99       def find_hudson_builds(job)
100         return [] unless job
101 
102         if filters.has_key?('hudson_build')
103           cond_builds = conditions_for('hudson_build', operator_for('hudson_build'), values_for('hudson_build'))
104         else
105           cond_builds = "#{HudsonBuild.table_name}.id > 0" #always true
106         end
107 
108         return HudsonBuild.find(:all, :conditions => ["#{HudsonBuild.table_name}.hudson_job_id = ? and #{cond_builds}", job.id], :order => "#{HudsonBuild.table_name}.number DESC", :limit => Hudson.query_limit_builds_each_job)
109       end
110 
111       def find_hudson_jobs
112         return [] unless project
113 
114         if filters.has_key?('hudson_job')
115           cond_jobs = "#{HudsonJob.table_name}.project_id = #{project.id} and #{conditions_for('hudson_job', operator_for('hudson_job'), values_for('hudson_job'))}"
116         else
117           cond_jobs = "#{HudsonJob.table_name}.project_id = #{project.id}"
118         end
119         return HudsonJob.find(:all, :conditions => cond_jobs)
120       end
121 
122 
123       # conditions always true
124       def sql_for_always_true
125         return "#{Issue.table_name}.id > 0"
126       end
127 
128       # conditions always false
129       def sql_for_always_false
130         return "#{Issue.table_name}.id < 0"
131       end
132 
133       def sql_for_issues(hudson_changesets)
134 
135         return sql_for_always_false unless hudson_changesets
136         return sql_for_always_false if hudson_changesets.length == 0
137 
138         value_revisions = hudson_changesets.collect{|target| "#{connection.quote_string(target.revision.to_s)}"}.join(",")
139         sql = "#{Issue.table_name}.id in"
140         sql << "(select changesets_issues.issue_id from changesets_issues"
141         sql << " where changesets_issues.changeset_id in"
142         sql << "  (select #{Changeset.table_name}.id from #{Changeset.table_name}"
143         sql << "   where #{Changeset.table_name}.repository_id = #{project.repository.id}"
144         sql << "    and   #{Changeset.table_name}.revision in (#{value_revisions})"
145         sql << " )"
146         sql << ")"
147         
148         return sql
149       end
150 
151       def conditions_for(field, operator, value)
152         retval = ""
153 
154         available_filters
155         return retval unless @hudson_filters
156         filter = @hudson_filters.detect {|hfilter| hfilter.name == field}
157         return retval unless filter
158         db_table = filter.db_table
159         db_field = filter.db_field
160 
161         case operator
162         when "="
163           retval = "#{db_table}.#{db_field} IN (" + value.collect{|val| "'#{connection.quote_string(val)}'"}.join(",") + ")"
164         when "!"
165           retval = "(#{db_table}.#{db_field} IS NULL OR #{db_table}.#{db_field} NOT IN (" + value.collect{|val| "'#{connection.quote_string(val)}'"}.join(",") + "))"
166         when "!*"
167           retval = "#{db_table}.#{db_field} IS NULL"
168           retval << " OR #{db_table}.#{db_field} = ''"
169         when "*"
170           retval = "#{db_table}.#{db_field} IS NOT NULL"
171           retval << " AND #{db_table}.#{db_field} <> ''"
172         when ">="
173           retval = "#{db_table}.#{db_field} >= #{value.first.to_i}"
174         when "<="
175           retval = "#{db_table}.#{db_field} <= #{value.first.to_i}"
176         when "!~"
177           retval = "#{db_table}.#{db_field} NOT LIKE '%#{connection.quote_string(value.first.to_s.downcase)}%'"
178         end
179         return retval
180       end
181 
182       def hudson_filters
183 
184         @hudson_filters = []
185         return @hudson_filters unless project
186         return @hudson_filters unless @available_filters
187 
188         hudson = Hudson.find_by_project_id(project.id)
189         return @hudson_filters unless hudson
190 
191         @hudson_filters << HudsonQueryFilter.new("hudson_job",
192                                 { :type => :list_optional, :order => @available_filters.size + 1,
193                                   :values => HudsonJob.find(:all, :conditions => ["#{HudsonJob.table_name}.project_id = ?", project.id],
194                                               :order => "#{HudsonJob.table_name}.name").collect {|job|
195                                               next unless hudson.settings.job_include?(job.name)
196                                               [job.name, job.id.to_s]
197                                             }
198                                 },
199                                 HudsonJob.table_name,
200                                 "id")
201         @hudson_filters << HudsonQueryFilter.new("hudson_build",
202                                 { :type => :integer, :order => @available_filters.size + 2 },
203                                 HudsonBuild.table_name,
204                                 "number")
205 
206         return @hudson_filters
207 
208       end
209 
210     end #InstanceMethods
211 
212     module InstanceMethodsFor09Later
213       def sql_for_field_with_redmine_hudson(field, operator, value, db_table, db_field, is_custom_filter=false)
214         case field
215         when "hudson_build"
216           return sql_for_hudson_build(field, operator, value)
217 
218         when "hudson_job"
219           return sql_for_hudson_job(field, operator, value)
220 
221         else
222            return sql_for_field_without_redmine_hudson(field, operator, value, db_table, db_field, is_custom_filter)
223         end
224       end
225     end #InstanceMethodsFor09Later
226 
227     module InstanceMethodsFor08
228       def sql_for_field_with_redmine_hudson(field, value, db_table, db_field, is_custom_filter)
229         operator = operator_for field
230         case field
231         when "hudson_build"
232           return sql_for_hudson_build(field, operator, value)
233 
234         when "hudson_job"
235           return sql_for_hudson_job(field, operator, value)
236 
237         else
238            return sql_for_field_without_redmine_hudson(field, value, db_table, db_field, is_custom_filter)
239         end
240       end
241     end #InstanceMethodsFor08
242 
243   end #RedmineExt
244 end #RedmineHudson