diff options
Diffstat (limited to 'app/models/merge_request_diff.rb')
-rw-r--r-- | app/models/merge_request_diff.rb | 40 |
1 files changed, 22 insertions, 18 deletions
diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb index fb873ddbbab..2dc6796732f 100644 --- a/app/models/merge_request_diff.rb +++ b/app/models/merge_request_diff.rb @@ -113,14 +113,29 @@ class MergeRequestDiff < ApplicationRecord joins(merge_request: :metrics).where(condition) end + # This scope uses LATERAL JOIN to find the most recent MR diff association for the given merge requests. + # To avoid joining the merge_requests table, we build an in memory table using the merge request ids. + # Example: + # SELECT ... + # FROM (VALUES (MR_ID_1),(MR_ID_2)) merge_requests (id) + # INNER JOIN LATERAL (...) scope :latest_diff_for_merge_requests, -> (merge_requests) do - inner_select = MergeRequestDiff - .default_scoped - .distinct - .select("FIRST_VALUE(id) OVER (PARTITION BY merge_request_id ORDER BY created_at DESC) as id") - .where(merge_request: merge_requests) + mrs = Array(merge_requests) + return MergeRequestDiff.none if mrs.empty? - joins("INNER JOIN (#{inner_select.to_sql}) latest_diffs ON latest_diffs.id = merge_request_diffs.id") + merge_request_table = MergeRequest.arel_table + merge_request_diff_table = MergeRequestDiff.arel_table + + join_query = MergeRequestDiff + .where(merge_request_table[:id].eq(merge_request_diff_table[:merge_request_id])) + .order(created_at: :desc) + .limit(1) + + mr_id_list = mrs.map { |mr| "(#{Integer(mr.id)})" }.join(",") + + MergeRequestDiff + .from("(VALUES #{mr_id_list}) merge_requests (id)") + .joins("INNER JOIN LATERAL (#{join_query.to_sql}) #{MergeRequestDiff.table_name} ON TRUE") .includes(:merge_request_diff_commits) end @@ -665,10 +680,6 @@ class MergeRequestDiff < ApplicationRecord opening_external_diff do collection = merge_request_diff_files - if options[:include_context_commits] - collection += merge_request.merge_request_context_commit_diff_files - end - if paths = options[:paths] collection = collection.where('old_path IN (?) OR new_path IN (?)', paths, paths) end @@ -743,7 +754,6 @@ class MergeRequestDiff < ApplicationRecord end def reorder_diff_files! - return unless sort_diffs? return if sorted? || merge_request_diff_files.empty? diff_files = sort_diffs(merge_request_diff_files) @@ -762,14 +772,8 @@ class MergeRequestDiff < ApplicationRecord end def sort_diffs(diffs) - return diffs unless sort_diffs? - Gitlab::Diff::FileCollectionSorter.new(diffs).sort end - - def sort_diffs? - Feature.enabled?(:sort_diffs, project, default_enabled: :yaml) - end end -MergeRequestDiff.prepend_if_ee('EE::MergeRequestDiff') +MergeRequestDiff.prepend_mod_with('MergeRequestDiff') |