Feature #44409 ยป 0001-Skip-the-nested-set-self-join-in-Issue.load_visible_.patch
| app/models/issue.rb | ||
|---|---|---|
| 1258 | 1258 |
# Preloads visible total spent time for a collection of issues |
| 1259 | 1259 |
def self.load_visible_total_spent_hours(issues, user=User.current) |
| 1260 |
if issues.any? |
|
| 1260 |
return if issues.empty? |
|
| 1261 | ||
| 1262 |
if issues.all?(&:leaf?) |
|
| 1263 |
# None of the issues has subtasks, so the expensive nested set |
|
| 1264 |
# self-join can be skipped. |
|
| 1265 |
# Keep this query identical to the one in load_visible_spent_hours so |
|
| 1266 |
# that it is served from the query cache when both are called in the |
|
| 1267 |
# same request (e.g. IssuesController#show and #index). |
|
| 1268 |
hours_by_issue_id = TimeEntry.visible(user). |
|
| 1269 |
where(:issue_id => issues.map(&:id)).group(:issue_id).sum(:hours) |
|
| 1270 |
else |
|
| 1261 | 1271 |
hours_by_issue_id = TimeEntry.visible(user).joins(:issue). |
| 1262 | 1272 |
joins("JOIN #{Issue.table_name} parent ON parent.root_id = #{Issue.table_name}.root_id" +
|
| 1263 | 1273 |
" AND parent.lft <= #{Issue.table_name}.lft AND parent.rgt >= #{Issue.table_name}.rgt").
|
| 1264 | 1274 |
where("parent.id IN (?)", issues.map(&:id)).group("parent.id").sum(:hours)
|
| 1265 |
issues.each do |issue|
|
|
| 1266 |
issue.instance_variable_set :@total_spent_hours, (hours_by_issue_id[issue.id] || 0.0)
|
|
| 1267 |
end
|
|
| 1275 |
end
|
|
| 1276 |
issues.each do |issue|
|
|
| 1277 |
issue.instance_variable_set :@total_spent_hours, (hours_by_issue_id[issue.id] || 0.0)
|
|
| 1268 | 1278 |
end |
| 1269 | 1279 |
end |
| test/unit/issue_test.rb | ||
|---|---|---|
| 240 | 240 |
assert_include 'Parent task is invalid', issue.errors.full_messages |
| 241 | 241 |
end |
| 242 |
def test_load_visible_total_spent_hours_should_load_visible_hours_for_leaf_issues |
|
| 243 |
issues = Issue.where(:id => [1, 2]).to_a |
|
| 244 |
assert issues.all?(&:leaf?) |
|
| 245 |
user = User.generate! |
|
| 246 |
role = Role.generate!(:permissions => [:view_issues, :view_time_entries], :time_entries_visibility => 'own') |
|
| 247 |
User.add_to_project(user, Project.find(1), role) |
|
| 248 |
TimeEntry.generate!(:issue => issues[0], :hours => 100.0, :user => User.find(2)) |
|
| 249 |
TimeEntry.generate!(:issue => issues[1], :hours => 100.0, :user => User.find(2)) |
|
| 250 |
TimeEntry.generate!(:issue => issues[1], :hours => 2.5, :user => user) |
|
| 251 | ||
| 252 |
Issue.load_visible_total_spent_hours(issues, user) |
|
| 253 | ||
| 254 |
assert_equal 0.0, issues[0].total_spent_hours |
|
| 255 |
assert_equal 2.5, issues[1].total_spent_hours |
|
| 256 |
end |
|
| 257 | ||
| 242 | 258 |
def assert_visibility_match(user, issues) |
| 243 | 259 |
assert_equal issues.collect(&:id).sort, Issue.all.select {|issue| issue.visible?(user)}.collect(&:id).sort
|
| 244 | 260 |
end |