summaryrefslogtreecommitdiff
path: root/lib/gitlab/background_migration/migrate_stage_index.rb
blob: f921233460d64382cbb81fae0cbfdb5c8e161f2c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# frozen_string_literal: true
# rubocop:disable Style/Documentation

module Gitlab
  module BackgroundMigration
    class MigrateStageIndex
      def perform(start_id, stop_id)
        migrate_stage_index_sql(start_id.to_i, stop_id.to_i).tap do |sql|
          ActiveRecord::Base.connection.execute(sql)
        end
      end

      private

      def migrate_stage_index_sql(start_id, stop_id)
        if Gitlab::Database.postgresql?
          <<~SQL
            WITH freqs AS (
              SELECT stage_id, stage_idx, COUNT(*) AS freq FROM ci_builds
                WHERE stage_id BETWEEN #{start_id} AND #{stop_id}
                  AND stage_idx IS NOT NULL
                GROUP BY stage_id, stage_idx
            ), indexes AS (
              SELECT DISTINCT stage_id, first_value(stage_idx)
                OVER (PARTITION BY stage_id ORDER BY freq DESC) AS index
                FROM freqs
            )

            UPDATE ci_stages SET position = indexes.index
              FROM indexes WHERE indexes.stage_id = ci_stages.id
                AND ci_stages.position IS NULL;
          SQL
        else
          <<~SQL
            UPDATE ci_stages
              SET position =
                (SELECT stage_idx FROM ci_builds
                  WHERE ci_builds.stage_id = ci_stages.id
                  GROUP BY ci_builds.stage_idx ORDER BY COUNT(*) DESC LIMIT 1)
            WHERE ci_stages.id BETWEEN #{start_id} AND #{stop_id}
              AND ci_stages.position IS NULL
          SQL
        end
      end
    end
  end
end