From 1f70f761f12b70a1550ab182e6308f67d5950571 Mon Sep 17 00:00:00 2001 From: Jens Kraemer Date: Wed, 20 Mar 2019 18:08:03 +0800 Subject: [PATCH 1/2] introduces IssueQuery#lazy_issues --- app/models/issue_query.rb | 32 +++++++++++++++++++++++++++++--- test/unit/query_test.rb | 3 ++- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/app/models/issue_query.rb b/app/models/issue_query.rb index 7e8c2e6a8..78ec9b61c 100644 --- a/app/models/issue_query.rb +++ b/app/models/issue_query.rb @@ -293,6 +293,33 @@ class IssueQuery < Query limit(options[:limit]). offset(options[:offset]) + return preload_issues scope + rescue ::ActiveRecord::StatementInvalid => e + raise StatementInvalid.new(e.message) + end + + # Like #issues, but returns an enumerator that lazily loads batches of issues + # Valid options are :order, :offset, :limit, :include, :conditions + def lazy_issues(options={}) + issue_ids = self.issue_ids options + + return Enumerator.new(issue_ids.length) do |yielder| + + issue_ids.each_slice(500) do |chunked_ids| + # The FIELD() function is MySQL-specific + scope = Issue + .where(id: chunked_ids) + .order("FIELD(id,#{chunked_ids.join(',')})") + + preload_issues(scope).each do |issue| + yielder << issue + end + end + end + end + + # takes a scope, returns an array + def preload_issues(scope) scope = scope.preload([:tracker, :author, :assigned_to, :fixed_version, :category, :attachments] & columns.map(&:name)) if has_custom_field_column? scope = scope.preload(:custom_values) @@ -315,10 +342,9 @@ class IssueQuery < Query if has_column?(:last_notes) Issue.load_visible_last_notes(issues) end - issues - rescue ::ActiveRecord::StatementInvalid => e - raise StatementInvalid.new(e.message) + return issues end + private :preload_issues # Returns the issues ids def issue_ids(options={}) diff --git a/test/unit/query_test.rb b/test/unit/query_test.rb index ee004232c..9d692f48e 100644 --- a/test/unit/query_test.rb +++ b/test/unit/query_test.rb @@ -161,7 +161,8 @@ class QueryTest < ActiveSupport::TestCase def assert_query_result(expected, query) assert_nothing_raised do - assert_equal expected.map(&:id).sort, query.issues.map(&:id).sort + assert_equal expected.map(&:id).sort, query.issues.map(&:id).sort, 'issues wrong' + assert_equal expected.map(&:id).sort, query.lazy_issues.map(&:id).sort, 'lazy issues wrong' assert_equal expected.size, query.issue_count end end -- 2.11.0