Patch #33431 » time_query_performace_v4.patch
app/controllers/timelog_controller.rb | ||
---|---|---|
49 | 49 | |
50 | 50 |
respond_to do |format| |
51 | 51 |
format.html do |
52 |
@entry_count = scope.count
|
|
52 |
@entry_count = @query.query_count
|
|
53 | 53 |
@entry_pages = Paginator.new @entry_count, per_page_option, params['page'] |
54 | 54 |
@entries = scope.offset(@entry_pages.offset).limit(@entry_pages.per_page).to_a |
55 | 55 | |
56 | 56 |
render :layout => !request.xhr? |
57 | 57 |
end |
58 | 58 |
format.api do |
59 |
@entry_count = scope.count
|
|
59 |
@entry_count = @query.query_count
|
|
60 | 60 |
@offset, @limit = api_offset_and_limit |
61 | 61 |
@entries = scope.offset(@offset).limit(@limit).preload(:custom_values => :custom_field).to_a |
62 | 62 |
end |
app/models/time_entry_query.rb | ||
---|---|---|
141 | 141 |
end |
142 | 142 |
end |
143 | 143 | |
144 |
def query_count |
|
145 |
base_count_scope.count |
|
146 |
rescue ::ActiveRecord::StatementInvalid => e |
|
147 |
raise StatementInvalid.new(e.message) |
|
148 |
end |
|
149 | ||
150 |
def base_group_scope |
|
151 |
base_result_scope. |
|
152 |
joins(joins_for_order_statement(group_by_statement)). |
|
153 |
group(group_by_statement) |
|
154 |
end |
|
155 | ||
156 |
def total_for(column) |
|
157 |
total_with_scope(column, base_result_scope) |
|
158 |
end |
|
159 | ||
144 | 160 |
def base_scope |
145 |
TimeEntry.visible. |
|
146 |
joins(:project, :user). |
|
147 |
includes(:activity). |
|
148 |
references(:activity). |
|
149 |
left_join_issue. |
|
150 |
where(statement) |
|
161 |
TimeEntry.visible.where(statement) |
|
162 |
end |
|
163 | ||
164 |
def base_result_scope |
|
165 |
base_scope.joins(:activity, :user) |
|
166 |
.includes(:activity) |
|
167 |
.left_join_issue |
|
168 |
.where("#{Enumeration.table_name}.project_id = #{TimeEntry.table_name}.project_id " \ |
|
169 |
"AND #{Enumeration.table_name}.project_id = #{Project.table_name}.id " \ |
|
170 |
"OR #{Enumeration.table_name}.project_id IS NULL") |
|
171 |
end |
|
172 | ||
173 |
def base_count_scope |
|
174 |
scope = base_scope |
|
175 |
scope = scope.joins(:activity) if base_count_with_activity? |
|
176 |
scope = scope.joins(:user) if base_count_with_user_join? |
|
177 |
scope = scope.left_join_issue if base_count_with_issues? |
|
178 |
scope |
|
179 |
end |
|
180 | ||
181 |
def base_count_with_activity? |
|
182 |
has_filter?('activity_id') || group_by_column&.name == :activity |
|
183 |
end |
|
184 | ||
185 |
def base_count_with_user_join? |
|
186 |
has_filter?('user') || has_filter?('author') || group_by_column&.name == :user |
|
187 |
end |
|
188 | ||
189 |
def base_count_with_issues? |
|
190 |
filters&.map(&:first)&.detect { |f| f.start_with?('issue.') } || group_by_column&.name == :issue |
|
151 | 191 |
end |
152 | 192 | |
153 | 193 |
def results_scope(options={}) |
154 | 194 |
order_option = [group_by_sort_order, (options[:order] || sort_clause)].flatten.reject(&:blank?) |
155 | 195 | |
156 | 196 |
order_option << "#{TimeEntry.table_name}.id ASC" |
157 |
base_scope. |
|
197 |
base_result_scope.
|
|
158 | 198 |
order(order_option). |
159 | 199 |
joins(joins_for_order_statement(order_option.join(','))) |
160 | 200 |
end |
test/unit/time_entry_query_test.rb | ||
---|---|---|
143 | 143 |
time_entry_ids = q.results_scope.pluck(:id) |
144 | 144 |
paginated_time_entry_ids = [] |
145 | 145 |
# Test with a maximum of 2 records per page. |
146 |
((q.results_scope.count / 2) + 1).times do |i|
|
|
146 |
((q.query_count / 2) + 1).times do |i|
|
|
147 | 147 |
paginated_time_entry_ids += q.results_scope.offset((i * 2)).limit(2).pluck(:id) |
148 | 148 |
end |
149 | 149 | |
150 | 150 |
# Non-paginated time entry ids and paginated time entry ids should be in the same order. |
151 | 151 |
assert_equal time_entry_ids, paginated_time_entry_ids |
152 | 152 |
end |
153 | ||
154 |
def test_query_count |
|
155 |
q = TimeEntryQuery.new(:name => '_') |
|
156 |
entry_count = q.query_count |
|
157 |
assert_equal q.results_scope.size, entry_count |
|
158 |
end |
|
153 | 159 |
end |