Project

General

Profile

Defect #1143 » query_patch.rb

cforce cforce, 01/18/2013 02:03 AM

 
1
require 'redmine/version'
2

    
3
module RedmineHudson
4
  module RedmineExt
5

    
6
    def RedmineExt.redmine_090_or_higher?
7
      return !(Redmine::VERSION::MAJOR == 0 && Redmine::VERSION::MINOR < 9)
8
    end
9

    
10
    module QueryPatch
11
      def self.included(base) # :nodoc:
12
        base.extend(ClassMethods)
13

    
14
        base.send(:include, InstanceMethods)
15
        base.send(:include, InstanceMethodsFor09Later) if RedmineHudson::RedmineExt.redmine_090_or_higher?
16
        base.send(:include, InstanceMethodsFor08) unless RedmineHudson::RedmineExt.redmine_090_or_higher?
17

    
18
        # Same as typing in the class
19
        base.class_eval do
20
          unloadable # Send unloadable so it will not be unloaded in development
21

    
22
          alias_method_chain :available_filters, :redmine_hudson unless method_defined?(:available_filters_without_redmine_hudson)
23
          alias_method_chain :sql_for_field, :redmine_hudson unless method_defined?(:sql_for_field_without_redmine_hudson)
24
        end
25

    
26
      end
27
    end
28

    
29
    module ClassMethods
30

    
31
      unless Query.respond_to?(:available_columns=)
32
        # Setter for +available_columns+ that isn't provided by the core.
33
        def available_columns=(v)
34
          self.available_columns = (v)
35
        end
36
      end
37

    
38
      unless Query.respond_to?(:add_available_column)
39
        # Method to add a column to the +available_columns+ that isn't provided by the core.
40
        def add_available_column(column)
41
          self.available_columns << (column)
42
        end
43
      end
44
    end
45

    
46
    module InstanceMethods
47

    
48
      def available_filters_with_redmine_hudson
49
        return @available_filters if @available_filters
50

    
51
        available_filters_without_redmine_hudson
52

    
53
        return @available_filters unless project
54

    
55
        hudson_filters
56

    
57
        @hudson_filters.each do |filter|
58
          @available_filters[filter.name] = filter.available_values
59
        end
60
        return @available_filters
61
      end
62

    
63
      def sql_for_hudson_build(field, operator, value)
64
        return sql_for_always_false unless project
65

    
66
        hudson_changesets = find_hudson_changesets
67

    
68
        return sql_for_issues(hudson_changesets)
69
      end
70

    
71
      def sql_for_hudson_job(field, operator, value)
72
        return sql_for_always_false unless project
73

    
74
        if filters.has_key?('hudson_build')
75
          return sql_for_always_true
76
        end
77

    
78
        hudson_changesets = find_hudson_changesets
79

    
80
        return sql_for_issues(hudson_changesets)
81
      end
82

    
83
      def find_hudson_changesets
84

    
85
        retval = []
86
        find_hudson_jobs.each do |job|
87
          builds = find_hudson_builds(job)
88
          next if builds.length == 0
89
          cond_builds = builds.collect{|build| "#{connection.quote_string(build.id.to_s)}"}.join(",")
90
          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)
91
        end
92

    
93
        return retval
94

    
95
      end
96

    
97
      def find_hudson_builds(job)
98
        return [] unless job
99

    
100
        if filters.has_key?('hudson_build')
101
          cond_builds = conditions_for('hudson_build', operator_for('hudson_build'), values_for('hudson_build'))
102
        else
103
          cond_builds = "#{HudsonBuild.table_name}.id > 0" #always true
104
        end
105

    
106
        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)
107
      end
108

    
109
      def find_hudson_jobs
110
        return [] unless project
111

    
112
        if filters.has_key?('hudson_job')
113
          cond_jobs = "#{HudsonJob.table_name}.project_id = #{project.id} and #{conditions_for('hudson_job', operator_for('hudson_job'), values_for('hudson_job'))}"
114
        else
115
          cond_jobs = "#{HudsonJob.table_name}.project_id = #{project.id}"
116
        end
117
        return HudsonJob.find(:all, :conditions => cond_jobs)
118
      end
119

    
120

    
121
      # conditions always true
122
      def sql_for_always_true
123
        return "#{Issue.table_name}.id > 0"
124
      end
125

    
126
      # conditions always false
127
      def sql_for_always_false
128
        return "#{Issue.table_name}.id < 0"
129
      end
130

    
131
      def sql_for_issues(hudson_changesets)
132

    
133
        return sql_for_always_false unless hudson_changesets
134
        return sql_for_always_false if hudson_changesets.length == 0
135

    
136
        value_revisions = hudson_changesets.collect{|target| "#{connection.quote_string(target.revision.to_s)}"}.join(",")
137
        sql = "#{Issue.table_name}.id in"
138
        sql << "(select changesets_issues.issue_id from changesets_issues"
139
        sql << " where changesets_issues.changeset_id in"
140
        sql << "  (select #{Changeset.table_name}.id from #{Changeset.table_name}"
141
        sql << "   where #{Changeset.table_name}.repository_id = #{project.repository.id}"
142
        sql << "    and   #{Changeset.table_name}.revision in (#{value_revisions})"
143
        sql << " )"
144
        sql << ")"
145
        
146
        return sql
147
      end
148

    
149
      def conditions_for(field, operator, value)
150
        retval = ""
151

    
152
        available_filters
153
        return retval unless @hudson_filters
154
        filter = @hudson_filters.detect {|hfilter| hfilter.name == field}
155
        return retval unless filter
156
        db_table = filter.db_table
157
        db_field = filter.db_field
158

    
159
        case operator
160
        when "="
161
          retval = "#{db_table}.#{db_field} IN (" + value.collect{|val| "'#{connection.quote_string(val)}'"}.join(",") + ")"
162
        when "!"
163
          retval = "(#{db_table}.#{db_field} IS NULL OR #{db_table}.#{db_field} NOT IN (" + value.collect{|val| "'#{connection.quote_string(val)}'"}.join(",") + "))"
164
        when "!*"
165
          retval = "#{db_table}.#{db_field} IS NULL"
166
          retval << " OR #{db_table}.#{db_field} = ''"
167
        when "*"
168
          retval = "#{db_table}.#{db_field} IS NOT NULL"
169
          retval << " AND #{db_table}.#{db_field} <> ''"
170
        when ">="
171
          retval = "#{db_table}.#{db_field} >= #{value.first.to_i}"
172
        when "<="
173
          retval = "#{db_table}.#{db_field} <= #{value.first.to_i}"
174
        when "!~"
175
          retval = "#{db_table}.#{db_field} NOT LIKE '%#{connection.quote_string(value.first.to_s.downcase)}%'"
176
        end
177
        return retval
178
      end
179

    
180
      def hudson_filters
181

    
182
        @hudson_filters = []
183
        return @hudson_filters unless project
184
        return @hudson_filters unless @available_filters
185

    
186
        hudson = Hudson.find_by_project_id(project.id)
187
        return @hudson_filters unless hudson
188

    
189
        @hudson_filters << HudsonQueryFilter.new("hudson_job",
190
                                { :name   => l(:field_hudson_job), :type => :list_optional, :order => @available_filters.size + 1,
191
                                  :values => HudsonJob.find(:all, :conditions => ["#{HudsonJob.table_name}.project_id = ?", project.id],
192
                                              :order => "#{HudsonJob.table_name}.name").collect {|job|
193
                                              next unless hudson.settings.job_include?(job.name)
194
                                              [job.name, job.id.to_s]
195
                                            }
196
                                },
197
                                HudsonJob.table_name,
198
                                "id")
199
        @hudson_filters << HudsonQueryFilter.new("hudson_build",
200
                                { :name   => l(:field_hudson_build), :type => :integer, :order => @available_filters.size + 2 },
201
                                HudsonBuild.table_name,
202
                                "number")
203

    
204
        return @hudson_filters
205

    
206
      end
207

    
208
    end #InstanceMethods
209

    
210
    module InstanceMethodsFor09Later
211
      def sql_for_field_with_redmine_hudson(field, operator, value, db_table, db_field, is_custom_filter=false)
212
        case field
213
        when "hudson_build"
214
          return sql_for_hudson_build(field, operator, value)
215

    
216
        when "hudson_job"
217
          return sql_for_hudson_job(field, operator, value)
218

    
219
        else
220
           return sql_for_field_without_redmine_hudson(field, operator, value, db_table, db_field, is_custom_filter)
221
        end
222
      end
223
    end #InstanceMethodsFor09Later
224

    
225
    module InstanceMethodsFor08
226
      def sql_for_field_with_redmine_hudson(field, value, db_table, db_field, is_custom_filter)
227
        operator = operator_for field
228
        case field
229
        when "hudson_build"
230
          return sql_for_hudson_build(field, operator, value)
231

    
232
        when "hudson_job"
233
          return sql_for_hudson_job(field, operator, value)
234

    
235
        else
236
           return sql_for_field_without_redmine_hudson(field, value, db_table, db_field, is_custom_filter)
237
        end
238
      end
239
    end #InstanceMethodsFor08
240

    
241
  end #RedmineExt
242
end #RedmineHudson
    (1-1/1)